From 2d8e79889c3557bea7e07e14b3304f4163ed2734 Mon Sep 17 00:00:00 2001 From: Saramean Date: Fri, 20 Jun 2014 16:24:06 +0900 Subject: [PATCH 1/3] Saramean scheduler --- README-CORDOVA-WEBOS.md | 8 + README.md | 65 +- api/assets/busy.gif | Bin 0 -> 310 bytes api/assets/favicon.ico | Bin 0 -> 1150 bytes api/assets/manifest.json | 13 + api/assets/search-input-search.png | Bin 0 -> 447 bytes api/build/app.css | 889 ++++ api/build/app.js | 4372 ++++++++++++++++ api/build/enyo.css | 181 + api/build/enyo.js | 4283 ++++++++++++++++ api/icon.png | Bin 0 -> 7115 bytes api/index.html | 23 + assets/Diary.png | Bin 0 -> 7666 bytes assets/check.png | Bin 0 -> 13502 bytes assets/delete_button.png | Bin 0 -> 4767 bytes assets/dot.png | Bin 0 -> 6489 bytes assets/favicon.ico | Bin 0 -> 1150 bytes assets/left_arrow.png | Bin 0 -> 3673 bytes assets/month.png | Bin 0 -> 26463 bytes assets/right_arrow.png | Bin 0 -> 3676 bytes assets/week.png | Bin 0 -> 60585 bytes build/app.css | 1432 ++++++ build/app.js | 4447 +++++++++++++++++ build/enyo.css | 181 + build/enyo.js | 4308 ++++++++++++++++ debug.html | 23 + deploy.md | 52 + deploy/bootplate/assets/favicon.ico | Bin 0 -> 1150 bytes deploy/bootplate/build/app.css | 1432 ++++++ deploy/bootplate/build/app.js | 4447 +++++++++++++++++ deploy/bootplate/build/enyo.css | 181 + deploy/bootplate/build/enyo.js | 4283 ++++++++++++++++ deploy/bootplate/icon.png | Bin 0 -> 7115 bytes deploy/bootplate/index.html | 27 + deploy/bootplate/lib/onyx/LICENSE-2.0.txt | 202 + deploy/bootplate/lib/onyx/images/checkbox.png | Bin 0 -> 5462 bytes .../bootplate/lib/onyx/images/grabbutton.png | Bin 0 -> 676 bytes .../lib/onyx/images/gradient-invert.png | Bin 0 -> 255 bytes deploy/bootplate/lib/onyx/images/gradient.png | Bin 0 -> 255 bytes deploy/bootplate/lib/onyx/images/more.png | Bin 0 -> 2696 bytes .../onyx/images/progress-button-cancel.png | Bin 0 -> 2631 bytes .../lib/onyx/images/search-input-cancel.png | Bin 0 -> 303 bytes .../lib/onyx/images/search-input-search.png | Bin 0 -> 447 bytes .../lib/onyx/images/slider-handle.png | Bin 0 -> 3095 bytes .../lib/onyx/images/spinner-dark.gif | Bin 0 -> 1924 bytes .../lib/onyx/images/spinner-light.gif | Bin 0 -> 1924 bytes enyo/CONTRIBUTING md | 10 + enyo/LICENSE-2.0.txt | 202 + enyo/README.md | 146 + enyo/enyo.js | 41 + enyo/loader.js | 302 ++ enyo/minify/minify.bat | 6 + enyo/minify/minify.sh | 3 + enyo/minify/package.js | 4 + enyo/package.json | 19 + enyo/samples/AjaxSample.css | 14 + enyo/samples/AjaxSample.html | 21 + enyo/samples/AjaxSample.js | 37 + enyo/samples/GestureSample.css | 57 + enyo/samples/GestureSample.html | 21 + enyo/samples/GestureSample.js | 198 + enyo/samples/JsonpSample.css | 14 + enyo/samples/JsonpSample.html | 21 + enyo/samples/JsonpSample.js | 29 + enyo/samples/PlatformSample.css | 11 + enyo/samples/PlatformSample.html | 21 + enyo/samples/PlatformSample.js | 36 + enyo/samples/Playground.css | 29 + enyo/samples/Playground.html | 23 + enyo/samples/Playground.js | 54 + enyo/samples/RepeaterSample.css | 9 + enyo/samples/RepeaterSample.html | 21 + enyo/samples/RepeaterSample.js | 52 + enyo/samples/ScrollerSample.css | 9 + enyo/samples/ScrollerSample.html | 21 + enyo/samples/ScrollerSample.js | 78 + enyo/samples/WebServiceSample.css | 14 + enyo/samples/WebServiceSample.html | 21 + enyo/samples/WebServiceSample.js | 32 + enyo/samples/assets/Sample1.js | 15 + enyo/samples/assets/Sample2.js | 15 + enyo/samples/assets/Sample3.js | 30 + enyo/samples/assets/Sample4.js | 24 + enyo/samples/package.js | 19 + enyo/source/ajax/Ajax.js | 255 + enyo/source/ajax/AjaxProperties.js | 68 + enyo/source/ajax/Async.js | 128 + enyo/source/ajax/Jsonp.js | 123 + enyo/source/ajax/WebService.js | 114 + enyo/source/ajax/cookie.js | 50 + enyo/source/ajax/formdata.js | 91 + enyo/source/ajax/json.js | 21 + enyo/source/ajax/package.js | 11 + enyo/source/ajax/xhr.js | 143 + enyo/source/boot/boot.js | 133 + enyo/source/boot/enyo.js | 31 + enyo/source/boot/package.js | 5 + enyo/source/dom/Control.js | 879 ++++ enyo/source/dom/animation.js | 99 + enyo/source/dom/dispatcher.js | 177 + enyo/source/dom/dom.css | 100 + enyo/source/dom/dom.js | 231 + enyo/source/dom/drag.js | 266 + enyo/source/dom/gesture.js | 172 + enyo/source/dom/modal.js | 49 + enyo/source/dom/package.js | 15 + enyo/source/dom/phonegap.js | 46 + enyo/source/dom/platform.js | 90 + enyo/source/dom/preview.js | 36 + enyo/source/dom/transform.js | 139 + enyo/source/dom/transition.js | 5 + enyo/source/kernel/Component.js | 547 ++ enyo/source/kernel/Layout.js | 34 + enyo/source/kernel/Object.js | 143 + enyo/source/kernel/Oop.js | 218 + enyo/source/kernel/Signals.js | 44 + enyo/source/kernel/UiComponent.js | 316 ++ enyo/source/kernel/job.js | 33 + enyo/source/kernel/lang.js | 416 ++ enyo/source/kernel/log.js | 98 + enyo/source/kernel/macroize.js | 74 + enyo/source/kernel/package.js | 12 + enyo/source/package.js | 7 + enyo/source/touch/ScrollMath.js | 305 ++ enyo/source/touch/ScrollStrategy.js | 186 + enyo/source/touch/Scroller.css | 19 + enyo/source/touch/Scroller.js | 344 ++ enyo/source/touch/Thumb.css | 22 + enyo/source/touch/Thumb.js | 111 + enyo/source/touch/TouchScrollStrategy.js | 429 ++ enyo/source/touch/TransitionScrollStrategy.js | 616 +++ enyo/source/touch/TranslateScrollStrategy.js | 157 + enyo/source/touch/gesture.js | 130 + enyo/source/touch/msevents.js | 93 + enyo/source/touch/package.js | 14 + enyo/source/touch/touch.js | 139 + enyo/source/ui/Animator.js | 132 + enyo/source/ui/BaseLayout.js | 22 + enyo/source/ui/Button.js | 42 + enyo/source/ui/Checkbox.js | 77 + enyo/source/ui/DragAvatar.js | 90 + enyo/source/ui/FloatingLayer.js | 38 + enyo/source/ui/Group.js | 46 + enyo/source/ui/GroupItem.js | 28 + enyo/source/ui/Image.js | 28 + enyo/source/ui/Input.js | 148 + enyo/source/ui/Popup.js | 303 ++ enyo/source/ui/Repeater.js | 108 + enyo/source/ui/RichText.js | 138 + enyo/source/ui/Select.js | 116 + enyo/source/ui/Selection.js | 171 + enyo/source/ui/Table.js | 36 + enyo/source/ui/TextArea.js | 20 + enyo/source/ui/ToolDecorator.js | 9 + enyo/source/ui/package.js | 21 + enyo/source/ui/ui.css | 26 + enyo/tools/README.md | 23 + enyo/tools/deploy.js | 230 + enyo/tools/lessc.bat | 17 + enyo/tools/lessc.sh | 18 + enyo/tools/minifier/lessc.js | 80 + enyo/tools/minifier/minify.js | 231 + .../minifier/node_modules/less/CHANGELOG.md | 49 + enyo/tools/minifier/node_modules/less/LICENSE | 179 + .../tools/minifier/node_modules/less/Makefile | 76 + .../minifier/node_modules/less/README.md | 28 + .../less/benchmark/benchmark.less | 3979 +++++++++++++++ .../less/benchmark/less-benchmark.js | 47 + .../minifier/node_modules/less/bin/lessc | 160 + .../minifier/node_modules/less/build/amd.js | 6 + .../node_modules/less/build/ecma-5.js | 120 + .../node_modules/less/build/header.js | 7 + .../node_modules/less/build/require-rhino.js | 7 + .../node_modules/less/build/require.js | 7 + .../node_modules/less/dist/less-1.1.0.js | 2695 ++++++++++ .../node_modules/less/dist/less-1.1.0.min.js | 16 + .../node_modules/less/dist/less-1.1.1.js | 2710 ++++++++++ .../node_modules/less/dist/less-1.1.1.min.js | 16 + .../node_modules/less/dist/less-1.1.2.js | 2712 ++++++++++ .../node_modules/less/dist/less-1.1.2.min.js | 16 + .../node_modules/less/dist/less-1.1.3.js | 2721 ++++++++++ .../node_modules/less/dist/less-1.1.3.min.js | 16 + .../node_modules/less/dist/less-1.1.4.js | 2769 ++++++++++ .../node_modules/less/dist/less-1.1.4.min.js | 16 + .../node_modules/less/dist/less-1.1.5.js | 2805 +++++++++++ .../node_modules/less/dist/less-1.1.5.min.js | 9 + .../node_modules/less/dist/less-1.1.6.js | 3004 +++++++++++ .../node_modules/less/dist/less-1.1.6.min.js | 9 + .../node_modules/less/dist/less-1.2.0.js | 3293 ++++++++++++ .../node_modules/less/dist/less-1.2.0.min.js | 9 + .../node_modules/less/dist/less-1.2.1.js | 3318 ++++++++++++ .../node_modules/less/dist/less-1.2.1.min.js | 9 + .../node_modules/less/dist/less-1.2.2.js | 3337 +++++++++++++ .../node_modules/less/dist/less-1.2.2.min.js | 9 + .../node_modules/less/dist/less-1.3.0.js | 3478 +++++++++++++ .../node_modules/less/dist/less-1.3.0.min.js | 9 + .../node_modules/less/dist/less-1.3.0e.js | 4017 +++++++++++++++ .../node_modules/less/dist/less-1.3.0e.min.js | 9 + .../less/dist/less-rhino-1.1.3.js | 2460 +++++++++ .../less/dist/less-rhino-1.1.5.js | 2481 +++++++++ .../node_modules/less/lib/less/browser.js | 394 ++ .../node_modules/less/lib/less/colors.js | 152 + .../node_modules/less/lib/less/cssmin.js | 355 ++ .../node_modules/less/lib/less/functions.js | 337 ++ .../node_modules/less/lib/less/index.js | 140 + .../less/lib/less/lessc_helper.js | 59 + .../node_modules/less/lib/less/parser.js | 1445 ++++++ .../node_modules/less/lib/less/rhino.js | 123 + .../node_modules/less/lib/less/tree.js | 43 + .../node_modules/less/lib/less/tree/alpha.js | 17 + .../less/lib/less/tree/anonymous.js | 27 + .../less/lib/less/tree/assignment.js | 19 + .../node_modules/less/lib/less/tree/call.js | 48 + .../node_modules/less/lib/less/tree/color.js | 111 + .../less/lib/less/tree/comment.js | 14 + .../less/lib/less/tree/condition.js | 42 + .../less/lib/less/tree/dimension.js | 49 + .../less/lib/less/tree/directive.js | 39 + .../less/lib/less/tree/element.js | 48 + .../less/lib/less/tree/expression.js | 23 + .../node_modules/less/lib/less/tree/import.js | 83 + .../less/lib/less/tree/javascript.js | 51 + .../less/lib/less/tree/keyword.js | 19 + .../node_modules/less/lib/less/tree/media.js | 123 + .../node_modules/less/lib/less/tree/mixin.js | 146 + .../less/lib/less/tree/operation.js | 32 + .../node_modules/less/lib/less/tree/paren.js | 16 + .../node_modules/less/lib/less/tree/quoted.js | 43 + .../node_modules/less/lib/less/tree/ratio.js | 13 + .../node_modules/less/lib/less/tree/rule.js | 42 + .../less/lib/less/tree/ruleset.js | 374 ++ .../less/lib/less/tree/selector.js | 47 + .../node_modules/less/lib/less/tree/url.js | 29 + .../node_modules/less/lib/less/tree/value.js | 24 + .../less/lib/less/tree/variable.js | 26 + .../minifier/node_modules/less/package.json | 17 + .../node_modules/less/test/css/colors.css | 77 + .../node_modules/less/test/css/comments.css | 56 + .../node_modules/less/test/css/css-3.css | 98 + .../less/test/css/css-escapes.css | 24 + .../node_modules/less/test/css/css.css | 100 + .../less/test/css/debug/linenumbers-all.css | 39 + .../test/css/debug/linenumbers-comments.css | 32 + .../test/css/debug/linenumbers-mediaquery.css | 32 + .../node_modules/less/test/css/functions.css | 92 + .../node_modules/less/test/css/ie-filters.css | 9 + .../less/test/css/import-once.css | 6 + .../node_modules/less/test/css/import.css | 23 + .../node_modules/less/test/css/javascript.css | 23 + .../node_modules/less/test/css/lazy-eval.css | 3 + .../node_modules/less/test/css/media.css | 176 + .../less/test/css/mixins-args.css | 74 + .../less/test/css/mixins-closure.css | 9 + .../less/test/css/mixins-guards.css | 68 + .../less/test/css/mixins-important.css | 17 + .../less/test/css/mixins-named-args.css | 20 + .../less/test/css/mixins-nested.css | 14 + .../less/test/css/mixins-pattern.css | 47 + .../node_modules/less/test/css/mixins.css | 108 + .../node_modules/less/test/css/operations.css | 49 + .../node_modules/less/test/css/parens.css | 20 + .../node_modules/less/test/css/rulesets.css | 33 + .../node_modules/less/test/css/scope.css | 15 + .../node_modules/less/test/css/selectors.css | 130 + .../node_modules/less/test/css/strings.css | 40 + .../node_modules/less/test/css/variables.css | 27 + .../node_modules/less/test/css/whitespace.css | 42 + .../node_modules/less/test/less-test.js | 174 + .../node_modules/less/test/less/colors.less | 88 + .../node_modules/less/test/less/comments.less | 65 + .../node_modules/less/test/less/css-3.less | 108 + .../less/test/less/css-escapes.less | 33 + .../node_modules/less/test/less/css.less | 115 + .../less/test/less/debug/import/test.less | 23 + .../less/test/less/debug/linenumbers.less | 21 + .../test/less/errors/comment-in-selector.less | 1 + .../test/less/errors/comment-in-selector.txt | 2 + .../less/test/less/errors/import-missing.less | 1 + .../less/test/less/errors/import-missing.txt | 3 + .../less/test/less/errors/import-no-semi.less | 1 + .../less/test/less/errors/import-no-semi.txt | 2 + .../test/less/errors/import-subfolder1.less | 1 + .../test/less/errors/import-subfolder1.txt | 3 + .../test/less/errors/import-subfolder2.less | 1 + .../test/less/errors/import-subfolder2.txt | 2 + .../errors/imports/import-subfolder1.less | 1 + .../errors/imports/import-subfolder2.less | 1 + .../imports/subfolder/mixin-not-defined.less | 1 + .../subfolder/parse-error-curly-bracket.less | 1 + .../test/less/errors/javascript-error.less | 3 + .../test/less/errors/javascript-error.txt | 4 + .../test/less/errors/mixin-not-defined.less | 11 + .../test/less/errors/mixin-not-defined.txt | 3 + .../errors/parse-error-curly-bracket.less | 1 + .../less/errors/parse-error-curly-bracket.txt | 2 + .../errors/parse-error-missing-bracket.less | 2 + .../errors/parse-error-missing-bracket.txt | 2 + .../test/less/errors/property-ie5-hack.less | 3 + .../test/less/errors/property-ie5-hack.txt | 4 + .../less/test/less/functions.less | 101 + .../less/test/less/ie-filters.less | 15 + .../less/test/less/import-once.less | 3 + .../node_modules/less/test/less/import.less | 11 + .../import/deeper/import-once-test-a.less | 1 + .../test/less/import/import-once-test-c.less | 7 + .../less/test/less/import/import-test-a.less | 2 + .../less/test/less/import/import-test-b.less | 8 + .../less/test/less/import/import-test-c.less | 7 + .../less/test/less/import/import-test-d.css | 1 + .../less/test/less/import/import-test-e.less | 2 + .../less/test/less/javascript.less | 29 + .../less/test/less/lazy-eval.less | 6 + .../node_modules/less/test/less/media.less | 179 + .../less/test/less/mixins-args.less | 130 + .../less/test/less/mixins-closure.less | 26 + .../less/test/less/mixins-guards.less | 113 + .../less/test/less/mixins-important.less | 18 + .../less/test/less/mixins-named-args.less | 31 + .../less/test/less/mixins-nested.less | 22 + .../less/test/less/mixins-pattern.less | 99 + .../node_modules/less/test/less/mixins.less | 93 + .../less/test/less/operations.less | 62 + .../node_modules/less/test/less/parens.less | 26 + .../node_modules/less/test/less/rulesets.less | 30 + .../node_modules/less/test/less/scope.less | 32 + .../less/test/less/selectors.less | 131 + .../node_modules/less/test/less/strings.less | 51 + .../less/test/less/variables.less | 54 + .../less/test/less/whitespace.less | 44 + .../node_modules/uglify-js/.npmignore | 6 + .../node_modules/uglify-js/README.html | 981 ++++ .../node_modules/uglify-js/README.org | 578 +++ .../node_modules/uglify-js/bin/uglifyjs | 335 ++ .../node_modules/uglify-js/docstyle.css | 75 + .../uglify-js/lib/consolidator.js | 1220 +++++ .../node_modules/uglify-js/lib/parse-js.js | 1364 +++++ .../node_modules/uglify-js/lib/process.js | 2091 ++++++++ .../uglify-js/lib/squeeze-more.js | 74 + .../node_modules/uglify-js/package.json | 30 + .../node_modules/uglify-js/test/beautify.js | 28 + .../node_modules/uglify-js/test/testparser.js | 409 ++ .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue278.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue278.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + .../uglify-js/test/unit/scripts.js | 57 + .../node_modules/uglify-js/tmp/hoist.js | 33 + .../node_modules/uglify-js/tmp/instrument.js | 97 + .../node_modules/uglify-js/tmp/test.js | 30 + .../node_modules/uglify-js/uglify-js.js | 18 + enyo/tools/minifier/node_modules/walker.js | 40 + enyo/tools/minifier/path-relative-shim.js | 135 + enyo/tools/minify.bat | 17 + enyo/tools/minify.sh | 18 + enyo/tools/node_modules/.bin/nopt | 44 + enyo/tools/node_modules/.bin/shjs | 43 + enyo/tools/node_modules/nopt/.npmignore | 0 enyo/tools/node_modules/nopt/LICENSE | 23 + enyo/tools/node_modules/nopt/README.md | 210 + enyo/tools/node_modules/nopt/bin/nopt.js | 44 + .../node_modules/nopt/examples/my-program.js | 30 + enyo/tools/node_modules/nopt/lib/nopt.js | 555 ++ .../nopt/node_modules/abbrev/README.md | 23 + .../nopt/node_modules/abbrev/lib/abbrev.js | 106 + .../nopt/node_modules/abbrev/package.json | 20 + enyo/tools/node_modules/nopt/package.json | 31 + .../node_modules/shelljs/.documentup.json | 6 + enyo/tools/node_modules/shelljs/.travis.yml | 6 + enyo/tools/node_modules/shelljs/LICENSE | 26 + enyo/tools/node_modules/shelljs/README.md | 421 ++ enyo/tools/node_modules/shelljs/bin/shjs | 43 + enyo/tools/node_modules/shelljs/global.js | 3 + enyo/tools/node_modules/shelljs/make.js | 46 + enyo/tools/node_modules/shelljs/package.json | 39 + .../node_modules/shelljs/scripts/docs.js | 15 + .../node_modules/shelljs/scripts/run-tests.js | 22 + enyo/tools/node_modules/shelljs/shell.js | 1513 ++++++ .../node_modules/shelljs/test/.npmignore | 2 + enyo/tools/node_modules/shelljs/test/cat.js | 57 + enyo/tools/node_modules/shelljs/test/cd.js | 64 + enyo/tools/node_modules/shelljs/test/cp.js | 130 + enyo/tools/node_modules/shelljs/test/echo.js | 50 + enyo/tools/node_modules/shelljs/test/env.js | 19 + enyo/tools/node_modules/shelljs/test/exec.js | 93 + enyo/tools/node_modules/shelljs/test/find.js | 56 + enyo/tools/node_modules/shelljs/test/grep.js | 59 + enyo/tools/node_modules/shelljs/test/ls.js | 202 + enyo/tools/node_modules/shelljs/test/mkdir.js | 79 + enyo/tools/node_modules/shelljs/test/mv.js | 130 + enyo/tools/node_modules/shelljs/test/pwd.js | 28 + .../node_modules/shelljs/test/resources/a.txt | 11 + .../node_modules/shelljs/test/resources/cp/a | 1 + .../node_modules/shelljs/test/resources/cp/b | 1 + .../shelljs/test/resources/cp/dir_a/z | 1 + .../resources/cp/dir_b/dir_b_a/dir_b_a_a/z | 1 + .../test/resources/external/node_script.js | 2 + .../test/resources/external/tmp/output | 0 .../test/resources/external/tmp/tempscript.js | 1 + .../node_modules/shelljs/test/resources/file1 | 1 + .../shelljs/test/resources/file1.js | 1 + .../shelljs/test/resources/file1.txt | 1 + .../node_modules/shelljs/test/resources/file2 | 1 + .../shelljs/test/resources/file2.js | 1 + .../shelljs/test/resources/file2.txt | 1 + .../shelljs/test/resources/find/.hidden | 1 + .../shelljs/test/resources/find/a | 1 + .../shelljs/test/resources/find/b | 1 + .../shelljs/test/resources/find/dir1/a_dir1 | 1 + .../test/resources/find/dir1/dir11/a_dir11 | 1 + .../shelljs/test/resources/find/dir2/a_dir1 | 1 + .../test/resources/ls/.hidden_dir/nada | 1 + .../shelljs/test/resources/ls/.hidden_file | 1 + .../test/resources/ls/a_dir/.hidden_dir/nada | 1 + .../shelljs/test/resources/ls/a_dir/b_dir/z | 1 + .../shelljs/test/resources/ls/a_dir/nada | 1 + .../shelljs/test/resources/ls/file1 | 1 + .../shelljs/test/resources/ls/file1.js | 1 + .../shelljs/test/resources/ls/file2 | 1 + .../shelljs/test/resources/ls/file2.js | 1 + ...ilename(with)[chars$]^that.must+be-escaped | 1 + enyo/tools/node_modules/shelljs/test/rm.js | 183 + enyo/tools/node_modules/shelljs/test/sed.js | 58 + .../tools/node_modules/shelljs/test/silent.js | 26 + .../node_modules/shelljs/test/tempdir.js | 27 + enyo/tools/node_modules/shelljs/test/test.js | 83 + enyo/tools/node_modules/shelljs/test/to.js | 39 + enyo/tools/node_modules/shelljs/test/which.js | 38 + enyo/tools/test/ajax/index.html | 13 + enyo/tools/test/ajax/package.js | 3 + enyo/tools/test/ajax/php/redball.jpg | Bin 0 -> 396 bytes enyo/tools/test/ajax/php/test1.php | 18 + enyo/tools/test/ajax/php/test2.php | 54 + enyo/tools/test/ajax/php/test3.php | 15 + enyo/tools/test/ajax/php/test4.php | 22 + enyo/tools/test/ajax/php/test5.php | 20 + enyo/tools/test/ajax/php/test6.php | 31 + enyo/tools/test/ajax/tests/AjaxTest.js | 246 + enyo/tools/test/ajax/tests/JsonpTest.js | 29 + enyo/tools/test/ajax/tests/WebServiceTest.js | 112 + enyo/tools/test/ajax/tests/XhrTest.js | 16 + enyo/tools/test/ajax/tests/package.js | 6 + enyo/tools/test/core/index.html | 15 + enyo/tools/test/core/test.css | 33 + enyo/tools/test/core/test.js | 303 ++ enyo/tools/test/core/tests/AjaxTest.js | 53 + enyo/tools/test/core/tests/AsyncTest.js | 44 + .../test/core/tests/ComponentDispatchTest.js | 74 + .../test/core/tests/ComponentHandlersTest.js | 22 + enyo/tools/test/core/tests/ComponentTest.js | 28 + .../tools/test/core/tests/ControlPropsTest.js | 32 + enyo/tools/test/core/tests/ControlTest.js | 92 + .../test/core/tests/DecodePackagePathTest.js | 70 + enyo/tools/test/core/tests/JsonTest.js | 36 + enyo/tools/test/core/tests/KindTest.js | 41 + enyo/tools/test/core/tests/LoaderTest.js | 28 + .../tools/test/core/tests/PathResolverTest.js | 57 + .../core/tests/ViewportPositioningTest.js | 104 + enyo/tools/test/core/tests/langTest.js | 54 + enyo/tools/test/core/tests/loader1.js | 1 + enyo/tools/test/core/tests/loader2a.js | 1 + enyo/tools/test/core/tests/loader2b.js | 1 + enyo/tools/test/core/tests/package.js | 16 + gallery_images/Saramean.scheduler.jpg | Bin 0 -> 37999 bytes gallery_manifest.json | 23 + icon.png | Bin 0 -> 7115 bytes index.html | 131 +- lib/layout/CONTRIBUTING md | 10 + lib/layout/README.md | 71 + lib/layout/deploy.bat | 0 lib/layout/deploy.sh | 0 lib/layout/design.js | 155 + lib/layout/fittable/package.js | 3 + .../fittable/samples/FittableAppLayout1.html | 22 + .../fittable/samples/FittableAppLayout1.js | 21 + .../fittable/samples/FittableAppLayout2.html | 22 + .../fittable/samples/FittableAppLayout2.js | 25 + .../fittable/samples/FittableAppLayout3.html | 22 + .../fittable/samples/FittableAppLayout3.js | 20 + .../fittable/samples/FittableAppLayout4.html | 22 + .../fittable/samples/FittableAppLayout4.js | 21 + .../fittable/samples/FittableDescription.html | 21 + .../fittable/samples/FittableDescription.js | 44 + .../fittable/samples/FittableSample.html | 21 + lib/layout/fittable/samples/FittableSample.js | 22 + .../fittable/samples/FittableTests.html | 21 + lib/layout/fittable/samples/FittableTests.js | 84 + lib/layout/fittable/samples/package.js | 9 + lib/layout/fittable/samples/sample.css | 76 + lib/layout/fittable/source/FittableColumns.js | 19 + lib/layout/fittable/source/FittableLayout.css | 69 + lib/layout/fittable/source/FittableLayout.js | 156 + lib/layout/fittable/source/FittableRows.js | 17 + lib/layout/fittable/source/package.js | 6 + lib/layout/imageview/package.js | 3 + .../imageview/samples/ImageCarouselSample.css | 8 + .../samples/ImageCarouselSample.html | 22 + .../imageview/samples/ImageCarouselSample.js | 74 + .../imageview/samples/ImageViewSample.css | 0 .../imageview/samples/ImageViewSample.html | 22 + .../imageview/samples/ImageViewSample.js | 28 + lib/layout/imageview/samples/assets/earth.jpg | Bin 0 -> 157230 bytes .../imageview/samples/assets/favicon.ico | Bin 0 -> 1150 bytes lib/layout/imageview/samples/assets/globe.jpg | Bin 0 -> 280339 bytes .../imageview/samples/assets/jupiter.jpg | Bin 0 -> 27149 bytes lib/layout/imageview/samples/assets/mars.jpg | Bin 0 -> 116236 bytes .../imageview/samples/assets/mercury.jpg | Bin 0 -> 206369 bytes .../imageview/samples/assets/neptune.jpg | Bin 0 -> 83489 bytes lib/layout/imageview/samples/assets/pin.png | Bin 0 -> 1341 bytes .../imageview/samples/assets/saturn.jpg | Bin 0 -> 75869 bytes .../imageview/samples/assets/uranus.jpg | Bin 0 -> 46984 bytes lib/layout/imageview/samples/assets/venus.jpg | Bin 0 -> 149675 bytes lib/layout/imageview/samples/package.js | 6 + lib/layout/imageview/source/ImageCarousel.js | 208 + lib/layout/imageview/source/ImageView.js | 379 ++ lib/layout/imageview/source/ImageViewPin.css | 5 + lib/layout/imageview/source/ImageViewPin.js | 123 + lib/layout/imageview/source/package.js | 6 + lib/layout/list/package.js | 3 + .../list/samples/FlyweightRepeaterSample.css | 16 + .../list/samples/FlyweightRepeaterSample.html | 23 + .../list/samples/FlyweightRepeaterSample.js | 59 + lib/layout/list/samples/ListAroundSample.css | 59 + lib/layout/list/samples/ListAroundSample.html | 23 + lib/layout/list/samples/ListAroundSample.js | 211 + lib/layout/list/samples/ListBasicSample.css | 28 + lib/layout/list/samples/ListBasicSample.html | 22 + lib/layout/list/samples/ListBasicSample.js | 27 + .../list/samples/ListContactsSample.css | 57 + .../list/samples/ListContactsSample.html | 23 + lib/layout/list/samples/ListContactsSample.js | 261 + .../list/samples/ListLanguagesSample.css | 64 + .../list/samples/ListLanguagesSample.html | 23 + .../list/samples/ListLanguagesSample.js | 160 + .../list/samples/ListNoSelectSample.html | 22 + lib/layout/list/samples/ListNoSelectSample.js | 26 + .../list/samples/ListOnyxItemSample.html | 23 + lib/layout/list/samples/ListOnyxItemSample.js | 39 + .../list/samples/ListPulldownSample.css | 15 + .../list/samples/ListPulldownSample.html | 22 + lib/layout/list/samples/ListPulldownSample.js | 97 + lib/layout/list/samples/NameGenerator.js | 48 + .../samples/PersistentSwipeableItemSample.css | 42 + .../PersistentSwipeableItemSample.html | 21 + .../samples/PersistentSwipeableItemSample.js | 60 + .../list/samples/assets/avatars/angel.png | Bin 0 -> 2476 bytes .../samples/assets/avatars/astrologer.png | Bin 0 -> 2142 bytes .../list/samples/assets/avatars/athlete.png | Bin 0 -> 2070 bytes .../list/samples/assets/avatars/baby.png | Bin 0 -> 1756 bytes .../list/samples/assets/avatars/clown.png | Bin 0 -> 2247 bytes .../list/samples/assets/avatars/devil.png | Bin 0 -> 2236 bytes .../list/samples/assets/avatars/doctor.png | Bin 0 -> 2184 bytes .../list/samples/assets/avatars/dude.png | Bin 0 -> 2196 bytes .../list/samples/assets/avatars/dude2.png | Bin 0 -> 2236 bytes .../list/samples/assets/avatars/dude3.png | Bin 0 -> 2067 bytes .../list/samples/assets/avatars/dude4.png | Bin 0 -> 2154 bytes .../list/samples/assets/avatars/dude5.png | Bin 0 -> 2065 bytes .../list/samples/assets/avatars/dude6.png | Bin 0 -> 2063 bytes lib/layout/list/samples/assets/bg.png | Bin 0 -> 79561 bytes .../list/samples/assets/item-hilite.png | Bin 0 -> 541 bytes lib/layout/list/samples/assets/pulldown.png | Bin 0 -> 3031 bytes lib/layout/list/samples/assets/pullup.png | Bin 0 -> 3028 bytes .../list/samples/assets/remove-icon.png | Bin 0 -> 2631 bytes .../samples/assets/search-input-search.png | Bin 0 -> 447 bytes lib/layout/list/samples/assets/spinner.gif | Bin 0 -> 664 bytes lib/layout/list/samples/package.js | 18 + lib/layout/list/source/AlphaJumpList.js | 37 + lib/layout/list/source/AlphaJumper.css | 36 + lib/layout/list/source/AlphaJumper.js | 70 + lib/layout/list/source/AroundList.js | 67 + lib/layout/list/source/FlyweightRepeater.js | 248 + lib/layout/list/source/List.css | 49 + lib/layout/list/source/List.js | 1502 ++++++ lib/layout/list/source/PulldownList.css | 60 + lib/layout/list/source/PulldownList.js | 202 + lib/layout/list/source/package.js | 8 + lib/layout/list/source/wip-package.js | 6 + lib/layout/package.js | 8 + lib/layout/panels/package.js | 3 + .../panels/samples/PanelsFlickrSample.css | 72 + .../panels/samples/PanelsFlickrSample.html | 23 + .../panels/samples/PanelsFlickrSample.js | 152 + lib/layout/panels/samples/PanelsSample.css | 40 + lib/layout/panels/samples/PanelsSample.html | 23 + lib/layout/panels/samples/PanelsSample.js | 108 + .../panels/samples/PanelsSlidingSample.css | 17 + .../panels/samples/PanelsSlidingSample.html | 23 + .../panels/samples/PanelsSlidingSample.js | 35 + .../samples/assets/search-input-search.png | Bin 0 -> 447 bytes .../panels/samples/assets/spinner-large.gif | Bin 0 -> 1924 bytes lib/layout/panels/samples/assets/spinner.gif | Bin 0 -> 664 bytes lib/layout/panels/samples/menutest.html | 59 + lib/layout/panels/samples/package.js | 8 + lib/layout/panels/source/Panels.css | 12 + lib/layout/panels/source/Panels.js | 427 ++ .../panels/source/arrangers/Arranger.css | 25 + .../panels/source/arrangers/Arranger.js | 230 + .../panels/source/arrangers/CardArranger.js | 53 + .../source/arrangers/CardSlideInArranger.js | 67 + .../source/arrangers/CarouselArranger.js | 117 + .../source/arrangers/CollapsingArranger.js | 101 + .../source/arrangers/DockRightArranger.js | 133 + .../panels/source/arrangers/OtherArrangers.js | 258 + lib/layout/panels/source/arrangers/package.js | 10 + lib/layout/panels/source/package.js | 5 + lib/layout/slideable/package.js | 3 + .../slideable/samples/SlideableSample.css | 41 + .../slideable/samples/SlideableSample.html | 22 + .../slideable/samples/SlideableSample.js | 98 + lib/layout/slideable/samples/package.js | 4 + lib/layout/slideable/source/Slideable.js | 316 ++ lib/layout/slideable/source/package.js | 3 + lib/layout/tree/package.js | 3 + lib/layout/tree/samples/TreeSample.css | 0 lib/layout/tree/samples/TreeSample.html | 22 + lib/layout/tree/samples/TreeSample.js | 43 + lib/layout/tree/samples/assets/file.png | Bin 0 -> 609 bytes .../tree/samples/assets/folder-open.png | Bin 0 -> 817 bytes lib/layout/tree/samples/assets/folder.png | Bin 0 -> 808 bytes lib/layout/tree/samples/package.js | 3 + lib/layout/tree/source/Node.css | 30 + lib/layout/tree/source/Node.js | 269 + lib/layout/tree/source/package.js | 4 + lib/onyx/CONTRIBUTING md | 44 + lib/onyx/LICENSE-2.0.txt | 202 + lib/onyx/README.md | 29 + lib/onyx/css/Button.less | 71 + lib/onyx/css/ButtonColors.less | 25 + lib/onyx/css/Checkbox.less | 20 + lib/onyx/css/ContextualPopup.less | 230 + lib/onyx/css/DatePicker.less | 14 + lib/onyx/css/Grabber.less | 7 + lib/onyx/css/Groupbox.less | 67 + lib/onyx/css/Icon.less | 21 + lib/onyx/css/Input.less | 45 + lib/onyx/css/Item.less | 24 + lib/onyx/css/Menu.less | 64 + lib/onyx/css/MoreToolbar.less | 30 + lib/onyx/css/Picker.less | 49 + lib/onyx/css/Popup.less | 14 + lib/onyx/css/ProgressBar.less | 69 + lib/onyx/css/ProgressButton.less | 33 + lib/onyx/css/RadioButton.less | 37 + lib/onyx/css/RangeSlider.less | 10 + lib/onyx/css/RichText.less | 26 + lib/onyx/css/Scrim.less | 23 + lib/onyx/css/Slider.less | 24 + lib/onyx/css/Spinner.less | 11 + lib/onyx/css/TabButton.less | 7 + lib/onyx/css/TextArea.less | 32 + lib/onyx/css/TimePicker.less | 12 + lib/onyx/css/ToggleButton.less | 65 + lib/onyx/css/Toolbar.less | 64 + lib/onyx/css/Tooltip.less | 70 + lib/onyx/css/onyx-rules.less | 78 + lib/onyx/css/onyx-variables.less | 140 + lib/onyx/css/onyx.css | 1153 +++++ lib/onyx/css/onyx.less | 5 + lib/onyx/css/package.js | 3 + lib/onyx/deploy.bat | 32 + lib/onyx/deploy.sh | 19 + lib/onyx/design/inline-controlled.html | 231 + lib/onyx/design/inline.html | 103 + lib/onyx/design/menu-icon-bookmark.png | Bin 0 -> 1883 bytes lib/onyx/design/toolbar-extended.html | 243 + lib/onyx/design/toolbar.html | 111 + lib/onyx/images/checkbox.png | Bin 0 -> 5462 bytes lib/onyx/images/grabbutton.png | Bin 0 -> 676 bytes lib/onyx/images/gradient-invert.png | Bin 0 -> 255 bytes lib/onyx/images/gradient.png | Bin 0 -> 255 bytes lib/onyx/images/more.png | Bin 0 -> 2696 bytes lib/onyx/images/progress-button-cancel.png | Bin 0 -> 2631 bytes lib/onyx/images/search-input-cancel.png | Bin 0 -> 303 bytes lib/onyx/images/search-input-search.png | Bin 0 -> 447 bytes lib/onyx/images/slider-handle.png | Bin 0 -> 3095 bytes lib/onyx/images/spinner-dark.gif | Bin 0 -> 1924 bytes lib/onyx/images/spinner-light.gif | Bin 0 -> 1924 bytes lib/onyx/package.js | 4 + lib/onyx/samples/ButtonGroupSample.html | 22 + lib/onyx/samples/ButtonGroupSample.js | 45 + lib/onyx/samples/ButtonSample.html | 22 + lib/onyx/samples/ButtonSample.js | 46 + lib/onyx/samples/CheckboxSample.html | 22 + lib/onyx/samples/CheckboxSample.js | 34 + lib/onyx/samples/ContextualPopupSample.html | 23 + lib/onyx/samples/ContextualPopupSample.js | 240 + lib/onyx/samples/DatePickerSample.html | 23 + lib/onyx/samples/DatePickerSample.js | 108 + lib/onyx/samples/DrawerSample.css | 33 + lib/onyx/samples/DrawerSample.html | 22 + lib/onyx/samples/DrawerSample.js | 41 + lib/onyx/samples/GroupboxSample.html | 22 + lib/onyx/samples/GroupboxSample.js | 40 + lib/onyx/samples/IconButtonSample.html | 22 + lib/onyx/samples/IconButtonSample.js | 61 + lib/onyx/samples/InputSample.html | 22 + lib/onyx/samples/InputSample.js | 68 + lib/onyx/samples/MenuSample.html | 22 + lib/onyx/samples/MenuSample.js | 99 + lib/onyx/samples/MoreToolbarSample.html | 22 + lib/onyx/samples/MoreToolbarSample.js | 35 + lib/onyx/samples/PickerSample.html | 22 + lib/onyx/samples/PickerSample.js | 101 + lib/onyx/samples/PopupSample.html | 22 + lib/onyx/samples/PopupSample.js | 65 + lib/onyx/samples/ProgressSample.html | 22 + lib/onyx/samples/ProgressSample.js | 81 + lib/onyx/samples/SliderSample.html | 22 + lib/onyx/samples/SliderSample.js | 98 + lib/onyx/samples/SpinnerSample.html | 22 + lib/onyx/samples/SpinnerSample.js | 18 + lib/onyx/samples/TimePickerSample.html | 23 + lib/onyx/samples/TimePickerSample.js | 100 + lib/onyx/samples/ToggleButtonSample.html | 22 + lib/onyx/samples/ToggleButtonSample.js | 35 + lib/onyx/samples/ToolbarSample.html | 23 + lib/onyx/samples/ToolbarSample.js | 66 + lib/onyx/samples/TooltipSample.html | 22 + lib/onyx/samples/TooltipSample.js | 92 + lib/onyx/samples/assets/favicon.ico | Bin 0 -> 1150 bytes lib/onyx/samples/assets/fish_bowl.png | Bin 0 -> 2632 bytes .../samples/assets/menu-icon-bookmark.png | Bin 0 -> 1883 bytes .../samples/assets/search-input-search.png | Bin 0 -> 447 bytes lib/onyx/samples/package.js | 23 + lib/onyx/samples/sample.css | 43 + lib/onyx/source/Button.js | 38 + lib/onyx/source/Checkbox.js | 34 + lib/onyx/source/ContextualPopup.js | 514 ++ lib/onyx/source/DatePicker.js | 205 + lib/onyx/source/Drawer.js | 115 + lib/onyx/source/FlyweightPicker.js | 131 + lib/onyx/source/Grabber.js | 19 + lib/onyx/source/Groupbox.js | 41 + lib/onyx/source/Icon.js | 37 + lib/onyx/source/IconButton.js | 54 + lib/onyx/source/Input.js | 19 + lib/onyx/source/InputDecorator.js | 61 + lib/onyx/source/IntegerPicker.js | 78 + lib/onyx/source/Item.js | 42 + lib/onyx/source/Menu.js | 193 + lib/onyx/source/MenuDecorator.js | 62 + lib/onyx/source/MenuItem.js | 66 + lib/onyx/source/MoreToolbar.js | 156 + lib/onyx/source/Picker.js | 103 + lib/onyx/source/PickerButton.js | 22 + lib/onyx/source/PickerDecorator.js | 30 + lib/onyx/source/Popup.js | 93 + lib/onyx/source/ProgressBar.js | 104 + lib/onyx/source/ProgressButton.js | 33 + lib/onyx/source/RadioButton.js | 13 + lib/onyx/source/RadioGroup.js | 20 + lib/onyx/source/RangeSlider.js | 227 + lib/onyx/source/RichText.js | 19 + lib/onyx/source/Scrim.js | 114 + lib/onyx/source/Slider.js | 136 + lib/onyx/source/Spinner.js | 31 + lib/onyx/source/TabPanels.js | 128 + lib/onyx/source/TextArea.js | 19 + lib/onyx/source/TimePicker.js | 210 + lib/onyx/source/ToggleButton.js | 118 + lib/onyx/source/ToggleIconButton.js | 58 + lib/onyx/source/Toolbar.js | 31 + lib/onyx/source/Tooltip.js | 86 + lib/onyx/source/TooltipDecorator.js | 45 + lib/onyx/source/design.js | 168 + lib/onyx/source/package.js | 42 + lib/onyx/source/wip-package.js | 3 + package.js | 11 +- source/Scheduler.css | 94 + source/Scheduler.js | 55 + source/Theme.less | 26 + source/function/calendar.css | 73 + source/function/calendar.js | 416 ++ source/function/package.js | 8 + source/function/to_do.css | 16 + source/function/to_do.js | 114 + source/function/weekly.css | 93 + source/function/weekly.js | 526 ++ source/package.js | 8 + tools/deploy.bat | 37 + tools/deploy.sh | 39 + 858 files changed, 130993 insertions(+), 178 deletions(-) create mode 100644 README-CORDOVA-WEBOS.md create mode 100644 api/assets/busy.gif create mode 100644 api/assets/favicon.ico create mode 100644 api/assets/manifest.json create mode 100644 api/assets/search-input-search.png create mode 100644 api/build/app.css create mode 100644 api/build/app.js create mode 100644 api/build/enyo.css create mode 100644 api/build/enyo.js create mode 100644 api/icon.png create mode 100644 api/index.html create mode 100644 assets/Diary.png create mode 100644 assets/check.png create mode 100644 assets/delete_button.png create mode 100644 assets/dot.png create mode 100644 assets/favicon.ico create mode 100644 assets/left_arrow.png create mode 100644 assets/month.png create mode 100644 assets/right_arrow.png create mode 100644 assets/week.png create mode 100644 build/app.css create mode 100644 build/app.js create mode 100644 build/enyo.css create mode 100644 build/enyo.js create mode 100644 debug.html create mode 100644 deploy.md create mode 100644 deploy/bootplate/assets/favicon.ico create mode 100644 deploy/bootplate/build/app.css create mode 100644 deploy/bootplate/build/app.js create mode 100644 deploy/bootplate/build/enyo.css create mode 100644 deploy/bootplate/build/enyo.js create mode 100644 deploy/bootplate/icon.png create mode 100644 deploy/bootplate/index.html create mode 100644 deploy/bootplate/lib/onyx/LICENSE-2.0.txt create mode 100644 deploy/bootplate/lib/onyx/images/checkbox.png create mode 100644 deploy/bootplate/lib/onyx/images/grabbutton.png create mode 100644 deploy/bootplate/lib/onyx/images/gradient-invert.png create mode 100644 deploy/bootplate/lib/onyx/images/gradient.png create mode 100644 deploy/bootplate/lib/onyx/images/more.png create mode 100644 deploy/bootplate/lib/onyx/images/progress-button-cancel.png create mode 100644 deploy/bootplate/lib/onyx/images/search-input-cancel.png create mode 100644 deploy/bootplate/lib/onyx/images/search-input-search.png create mode 100644 deploy/bootplate/lib/onyx/images/slider-handle.png create mode 100644 deploy/bootplate/lib/onyx/images/spinner-dark.gif create mode 100644 deploy/bootplate/lib/onyx/images/spinner-light.gif create mode 100644 enyo/CONTRIBUTING md create mode 100644 enyo/LICENSE-2.0.txt create mode 100644 enyo/README.md create mode 100644 enyo/enyo.js create mode 100644 enyo/loader.js create mode 100644 enyo/minify/minify.bat create mode 100644 enyo/minify/minify.sh create mode 100644 enyo/minify/package.js create mode 100644 enyo/package.json create mode 100644 enyo/samples/AjaxSample.css create mode 100644 enyo/samples/AjaxSample.html create mode 100644 enyo/samples/AjaxSample.js create mode 100644 enyo/samples/GestureSample.css create mode 100644 enyo/samples/GestureSample.html create mode 100644 enyo/samples/GestureSample.js create mode 100644 enyo/samples/JsonpSample.css create mode 100644 enyo/samples/JsonpSample.html create mode 100644 enyo/samples/JsonpSample.js create mode 100644 enyo/samples/PlatformSample.css create mode 100644 enyo/samples/PlatformSample.html create mode 100644 enyo/samples/PlatformSample.js create mode 100644 enyo/samples/Playground.css create mode 100644 enyo/samples/Playground.html create mode 100644 enyo/samples/Playground.js create mode 100644 enyo/samples/RepeaterSample.css create mode 100644 enyo/samples/RepeaterSample.html create mode 100644 enyo/samples/RepeaterSample.js create mode 100644 enyo/samples/ScrollerSample.css create mode 100644 enyo/samples/ScrollerSample.html create mode 100644 enyo/samples/ScrollerSample.js create mode 100644 enyo/samples/WebServiceSample.css create mode 100644 enyo/samples/WebServiceSample.html create mode 100644 enyo/samples/WebServiceSample.js create mode 100644 enyo/samples/assets/Sample1.js create mode 100644 enyo/samples/assets/Sample2.js create mode 100644 enyo/samples/assets/Sample3.js create mode 100644 enyo/samples/assets/Sample4.js create mode 100644 enyo/samples/package.js create mode 100644 enyo/source/ajax/Ajax.js create mode 100644 enyo/source/ajax/AjaxProperties.js create mode 100644 enyo/source/ajax/Async.js create mode 100644 enyo/source/ajax/Jsonp.js create mode 100644 enyo/source/ajax/WebService.js create mode 100644 enyo/source/ajax/cookie.js create mode 100644 enyo/source/ajax/formdata.js create mode 100644 enyo/source/ajax/json.js create mode 100644 enyo/source/ajax/package.js create mode 100644 enyo/source/ajax/xhr.js create mode 100644 enyo/source/boot/boot.js create mode 100644 enyo/source/boot/enyo.js create mode 100644 enyo/source/boot/package.js create mode 100644 enyo/source/dom/Control.js create mode 100644 enyo/source/dom/animation.js create mode 100644 enyo/source/dom/dispatcher.js create mode 100644 enyo/source/dom/dom.css create mode 100644 enyo/source/dom/dom.js create mode 100644 enyo/source/dom/drag.js create mode 100644 enyo/source/dom/gesture.js create mode 100644 enyo/source/dom/modal.js create mode 100644 enyo/source/dom/package.js create mode 100644 enyo/source/dom/phonegap.js create mode 100644 enyo/source/dom/platform.js create mode 100644 enyo/source/dom/preview.js create mode 100644 enyo/source/dom/transform.js create mode 100644 enyo/source/dom/transition.js create mode 100644 enyo/source/kernel/Component.js create mode 100644 enyo/source/kernel/Layout.js create mode 100644 enyo/source/kernel/Object.js create mode 100644 enyo/source/kernel/Oop.js create mode 100644 enyo/source/kernel/Signals.js create mode 100644 enyo/source/kernel/UiComponent.js create mode 100644 enyo/source/kernel/job.js create mode 100644 enyo/source/kernel/lang.js create mode 100644 enyo/source/kernel/log.js create mode 100644 enyo/source/kernel/macroize.js create mode 100644 enyo/source/kernel/package.js create mode 100644 enyo/source/package.js create mode 100644 enyo/source/touch/ScrollMath.js create mode 100644 enyo/source/touch/ScrollStrategy.js create mode 100644 enyo/source/touch/Scroller.css create mode 100644 enyo/source/touch/Scroller.js create mode 100644 enyo/source/touch/Thumb.css create mode 100644 enyo/source/touch/Thumb.js create mode 100644 enyo/source/touch/TouchScrollStrategy.js create mode 100644 enyo/source/touch/TransitionScrollStrategy.js create mode 100644 enyo/source/touch/TranslateScrollStrategy.js create mode 100644 enyo/source/touch/gesture.js create mode 100644 enyo/source/touch/msevents.js create mode 100644 enyo/source/touch/package.js create mode 100644 enyo/source/touch/touch.js create mode 100644 enyo/source/ui/Animator.js create mode 100644 enyo/source/ui/BaseLayout.js create mode 100644 enyo/source/ui/Button.js create mode 100644 enyo/source/ui/Checkbox.js create mode 100644 enyo/source/ui/DragAvatar.js create mode 100644 enyo/source/ui/FloatingLayer.js create mode 100644 enyo/source/ui/Group.js create mode 100644 enyo/source/ui/GroupItem.js create mode 100644 enyo/source/ui/Image.js create mode 100644 enyo/source/ui/Input.js create mode 100644 enyo/source/ui/Popup.js create mode 100644 enyo/source/ui/Repeater.js create mode 100644 enyo/source/ui/RichText.js create mode 100644 enyo/source/ui/Select.js create mode 100644 enyo/source/ui/Selection.js create mode 100644 enyo/source/ui/Table.js create mode 100644 enyo/source/ui/TextArea.js create mode 100644 enyo/source/ui/ToolDecorator.js create mode 100644 enyo/source/ui/package.js create mode 100644 enyo/source/ui/ui.css create mode 100644 enyo/tools/README.md create mode 100644 enyo/tools/deploy.js create mode 100644 enyo/tools/lessc.bat create mode 100644 enyo/tools/lessc.sh create mode 100644 enyo/tools/minifier/lessc.js create mode 100644 enyo/tools/minifier/minify.js create mode 100644 enyo/tools/minifier/node_modules/less/CHANGELOG.md create mode 100644 enyo/tools/minifier/node_modules/less/LICENSE create mode 100644 enyo/tools/minifier/node_modules/less/Makefile create mode 100644 enyo/tools/minifier/node_modules/less/README.md create mode 100644 enyo/tools/minifier/node_modules/less/benchmark/benchmark.less create mode 100644 enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js create mode 100644 enyo/tools/minifier/node_modules/less/bin/lessc create mode 100644 enyo/tools/minifier/node_modules/less/build/amd.js create mode 100644 enyo/tools/minifier/node_modules/less/build/ecma-5.js create mode 100644 enyo/tools/minifier/node_modules/less/build/header.js create mode 100644 enyo/tools/minifier/node_modules/less/build/require-rhino.js create mode 100644 enyo/tools/minifier/node_modules/less/build/require.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.1.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.2.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.3.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.4.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.5.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.6.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.0.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.1.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.2.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.3.js create mode 100644 enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/browser.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/colors.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/cssmin.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/functions.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/index.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/parser.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/rhino.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/call.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/color.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/element.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/import.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/media.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/url.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/value.js create mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js create mode 100644 enyo/tools/minifier/node_modules/less/package.json create mode 100644 enyo/tools/minifier/node_modules/less/test/css/colors.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/comments.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/css-3.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/css-escapes.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/css.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/functions.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/ie-filters.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/import-once.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/import.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/javascript.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/media.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-args.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-important.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/operations.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/parens.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/rulesets.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/scope.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/selectors.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/strings.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/variables.css create mode 100644 enyo/tools/minifier/node_modules/less/test/css/whitespace.css create mode 100644 enyo/tools/minifier/node_modules/less/test/less-test.js create mode 100644 enyo/tools/minifier/node_modules/less/test/less/colors.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/comments.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/css-3.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/css-escapes.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/css.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt create mode 100644 enyo/tools/minifier/node_modules/less/test/less/functions.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/ie-filters.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import-once.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css create mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/javascript.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/media.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-args.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-important.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/operations.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/parens.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/rulesets.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/scope.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/selectors.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/strings.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/variables.less create mode 100644 enyo/tools/minifier/node_modules/less/test/less/whitespace.less create mode 100644 enyo/tools/minifier/node_modules/uglify-js/.npmignore create mode 100644 enyo/tools/minifier/node_modules/uglify-js/README.html create mode 100644 enyo/tools/minifier/node_modules/uglify-js/README.org create mode 100644 enyo/tools/minifier/node_modules/uglify-js/bin/uglifyjs create mode 100644 enyo/tools/minifier/node_modules/uglify-js/docstyle.css create mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/consolidator.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/parse-js.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/process.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/squeeze-more.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/package.json create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/beautify.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/testparser.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue278.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue278.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/test.js create mode 100644 enyo/tools/minifier/node_modules/uglify-js/uglify-js.js create mode 100644 enyo/tools/minifier/node_modules/walker.js create mode 100644 enyo/tools/minifier/path-relative-shim.js create mode 100644 enyo/tools/minify.bat create mode 100644 enyo/tools/minify.sh create mode 100644 enyo/tools/node_modules/.bin/nopt create mode 100644 enyo/tools/node_modules/.bin/shjs create mode 100644 enyo/tools/node_modules/nopt/.npmignore create mode 100644 enyo/tools/node_modules/nopt/LICENSE create mode 100644 enyo/tools/node_modules/nopt/README.md create mode 100644 enyo/tools/node_modules/nopt/bin/nopt.js create mode 100644 enyo/tools/node_modules/nopt/examples/my-program.js create mode 100644 enyo/tools/node_modules/nopt/lib/nopt.js create mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/README.md create mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js create mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/package.json create mode 100644 enyo/tools/node_modules/nopt/package.json create mode 100644 enyo/tools/node_modules/shelljs/.documentup.json create mode 100644 enyo/tools/node_modules/shelljs/.travis.yml create mode 100644 enyo/tools/node_modules/shelljs/LICENSE create mode 100644 enyo/tools/node_modules/shelljs/README.md create mode 100644 enyo/tools/node_modules/shelljs/bin/shjs create mode 100644 enyo/tools/node_modules/shelljs/global.js create mode 100644 enyo/tools/node_modules/shelljs/make.js create mode 100644 enyo/tools/node_modules/shelljs/package.json create mode 100644 enyo/tools/node_modules/shelljs/scripts/docs.js create mode 100644 enyo/tools/node_modules/shelljs/scripts/run-tests.js create mode 100644 enyo/tools/node_modules/shelljs/shell.js create mode 100644 enyo/tools/node_modules/shelljs/test/.npmignore create mode 100644 enyo/tools/node_modules/shelljs/test/cat.js create mode 100644 enyo/tools/node_modules/shelljs/test/cd.js create mode 100644 enyo/tools/node_modules/shelljs/test/cp.js create mode 100644 enyo/tools/node_modules/shelljs/test/echo.js create mode 100644 enyo/tools/node_modules/shelljs/test/env.js create mode 100644 enyo/tools/node_modules/shelljs/test/exec.js create mode 100644 enyo/tools/node_modules/shelljs/test/find.js create mode 100644 enyo/tools/node_modules/shelljs/test/grep.js create mode 100644 enyo/tools/node_modules/shelljs/test/ls.js create mode 100644 enyo/tools/node_modules/shelljs/test/mkdir.js create mode 100644 enyo/tools/node_modules/shelljs/test/mv.js create mode 100644 enyo/tools/node_modules/shelljs/test/pwd.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/a.txt create mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/a create mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/b create mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z create mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z create mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/node_script.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/tmp/output create mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1.txt create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2.txt create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/.hidden create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/a create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/b create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file1 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file1.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file2 create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file2.js create mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped create mode 100644 enyo/tools/node_modules/shelljs/test/rm.js create mode 100644 enyo/tools/node_modules/shelljs/test/sed.js create mode 100644 enyo/tools/node_modules/shelljs/test/silent.js create mode 100644 enyo/tools/node_modules/shelljs/test/tempdir.js create mode 100644 enyo/tools/node_modules/shelljs/test/test.js create mode 100644 enyo/tools/node_modules/shelljs/test/to.js create mode 100644 enyo/tools/node_modules/shelljs/test/which.js create mode 100644 enyo/tools/test/ajax/index.html create mode 100644 enyo/tools/test/ajax/package.js create mode 100644 enyo/tools/test/ajax/php/redball.jpg create mode 100644 enyo/tools/test/ajax/php/test1.php create mode 100644 enyo/tools/test/ajax/php/test2.php create mode 100644 enyo/tools/test/ajax/php/test3.php create mode 100644 enyo/tools/test/ajax/php/test4.php create mode 100644 enyo/tools/test/ajax/php/test5.php create mode 100644 enyo/tools/test/ajax/php/test6.php create mode 100644 enyo/tools/test/ajax/tests/AjaxTest.js create mode 100644 enyo/tools/test/ajax/tests/JsonpTest.js create mode 100644 enyo/tools/test/ajax/tests/WebServiceTest.js create mode 100644 enyo/tools/test/ajax/tests/XhrTest.js create mode 100644 enyo/tools/test/ajax/tests/package.js create mode 100644 enyo/tools/test/core/index.html create mode 100644 enyo/tools/test/core/test.css create mode 100644 enyo/tools/test/core/test.js create mode 100644 enyo/tools/test/core/tests/AjaxTest.js create mode 100644 enyo/tools/test/core/tests/AsyncTest.js create mode 100644 enyo/tools/test/core/tests/ComponentDispatchTest.js create mode 100644 enyo/tools/test/core/tests/ComponentHandlersTest.js create mode 100644 enyo/tools/test/core/tests/ComponentTest.js create mode 100644 enyo/tools/test/core/tests/ControlPropsTest.js create mode 100644 enyo/tools/test/core/tests/ControlTest.js create mode 100644 enyo/tools/test/core/tests/DecodePackagePathTest.js create mode 100644 enyo/tools/test/core/tests/JsonTest.js create mode 100644 enyo/tools/test/core/tests/KindTest.js create mode 100644 enyo/tools/test/core/tests/LoaderTest.js create mode 100644 enyo/tools/test/core/tests/PathResolverTest.js create mode 100644 enyo/tools/test/core/tests/ViewportPositioningTest.js create mode 100644 enyo/tools/test/core/tests/langTest.js create mode 100644 enyo/tools/test/core/tests/loader1.js create mode 100644 enyo/tools/test/core/tests/loader2a.js create mode 100644 enyo/tools/test/core/tests/loader2b.js create mode 100644 enyo/tools/test/core/tests/package.js create mode 100644 gallery_images/Saramean.scheduler.jpg create mode 100644 icon.png create mode 100644 lib/layout/CONTRIBUTING md create mode 100644 lib/layout/README.md create mode 100644 lib/layout/deploy.bat create mode 100644 lib/layout/deploy.sh create mode 100644 lib/layout/design.js create mode 100644 lib/layout/fittable/package.js create mode 100644 lib/layout/fittable/samples/FittableAppLayout1.html create mode 100644 lib/layout/fittable/samples/FittableAppLayout1.js create mode 100644 lib/layout/fittable/samples/FittableAppLayout2.html create mode 100644 lib/layout/fittable/samples/FittableAppLayout2.js create mode 100644 lib/layout/fittable/samples/FittableAppLayout3.html create mode 100644 lib/layout/fittable/samples/FittableAppLayout3.js create mode 100644 lib/layout/fittable/samples/FittableAppLayout4.html create mode 100644 lib/layout/fittable/samples/FittableAppLayout4.js create mode 100644 lib/layout/fittable/samples/FittableDescription.html create mode 100644 lib/layout/fittable/samples/FittableDescription.js create mode 100644 lib/layout/fittable/samples/FittableSample.html create mode 100644 lib/layout/fittable/samples/FittableSample.js create mode 100644 lib/layout/fittable/samples/FittableTests.html create mode 100644 lib/layout/fittable/samples/FittableTests.js create mode 100644 lib/layout/fittable/samples/package.js create mode 100644 lib/layout/fittable/samples/sample.css create mode 100644 lib/layout/fittable/source/FittableColumns.js create mode 100644 lib/layout/fittable/source/FittableLayout.css create mode 100644 lib/layout/fittable/source/FittableLayout.js create mode 100644 lib/layout/fittable/source/FittableRows.js create mode 100644 lib/layout/fittable/source/package.js create mode 100644 lib/layout/imageview/package.js create mode 100644 lib/layout/imageview/samples/ImageCarouselSample.css create mode 100644 lib/layout/imageview/samples/ImageCarouselSample.html create mode 100644 lib/layout/imageview/samples/ImageCarouselSample.js create mode 100644 lib/layout/imageview/samples/ImageViewSample.css create mode 100644 lib/layout/imageview/samples/ImageViewSample.html create mode 100644 lib/layout/imageview/samples/ImageViewSample.js create mode 100644 lib/layout/imageview/samples/assets/earth.jpg create mode 100644 lib/layout/imageview/samples/assets/favicon.ico create mode 100644 lib/layout/imageview/samples/assets/globe.jpg create mode 100644 lib/layout/imageview/samples/assets/jupiter.jpg create mode 100644 lib/layout/imageview/samples/assets/mars.jpg create mode 100644 lib/layout/imageview/samples/assets/mercury.jpg create mode 100644 lib/layout/imageview/samples/assets/neptune.jpg create mode 100644 lib/layout/imageview/samples/assets/pin.png create mode 100644 lib/layout/imageview/samples/assets/saturn.jpg create mode 100644 lib/layout/imageview/samples/assets/uranus.jpg create mode 100644 lib/layout/imageview/samples/assets/venus.jpg create mode 100644 lib/layout/imageview/samples/package.js create mode 100644 lib/layout/imageview/source/ImageCarousel.js create mode 100644 lib/layout/imageview/source/ImageView.js create mode 100644 lib/layout/imageview/source/ImageViewPin.css create mode 100644 lib/layout/imageview/source/ImageViewPin.js create mode 100644 lib/layout/imageview/source/package.js create mode 100644 lib/layout/list/package.js create mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.css create mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.html create mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.js create mode 100644 lib/layout/list/samples/ListAroundSample.css create mode 100644 lib/layout/list/samples/ListAroundSample.html create mode 100644 lib/layout/list/samples/ListAroundSample.js create mode 100644 lib/layout/list/samples/ListBasicSample.css create mode 100644 lib/layout/list/samples/ListBasicSample.html create mode 100644 lib/layout/list/samples/ListBasicSample.js create mode 100644 lib/layout/list/samples/ListContactsSample.css create mode 100644 lib/layout/list/samples/ListContactsSample.html create mode 100644 lib/layout/list/samples/ListContactsSample.js create mode 100644 lib/layout/list/samples/ListLanguagesSample.css create mode 100644 lib/layout/list/samples/ListLanguagesSample.html create mode 100644 lib/layout/list/samples/ListLanguagesSample.js create mode 100644 lib/layout/list/samples/ListNoSelectSample.html create mode 100644 lib/layout/list/samples/ListNoSelectSample.js create mode 100644 lib/layout/list/samples/ListOnyxItemSample.html create mode 100644 lib/layout/list/samples/ListOnyxItemSample.js create mode 100644 lib/layout/list/samples/ListPulldownSample.css create mode 100644 lib/layout/list/samples/ListPulldownSample.html create mode 100644 lib/layout/list/samples/ListPulldownSample.js create mode 100644 lib/layout/list/samples/NameGenerator.js create mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.css create mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.html create mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.js create mode 100644 lib/layout/list/samples/assets/avatars/angel.png create mode 100644 lib/layout/list/samples/assets/avatars/astrologer.png create mode 100644 lib/layout/list/samples/assets/avatars/athlete.png create mode 100644 lib/layout/list/samples/assets/avatars/baby.png create mode 100644 lib/layout/list/samples/assets/avatars/clown.png create mode 100644 lib/layout/list/samples/assets/avatars/devil.png create mode 100644 lib/layout/list/samples/assets/avatars/doctor.png create mode 100644 lib/layout/list/samples/assets/avatars/dude.png create mode 100644 lib/layout/list/samples/assets/avatars/dude2.png create mode 100644 lib/layout/list/samples/assets/avatars/dude3.png create mode 100644 lib/layout/list/samples/assets/avatars/dude4.png create mode 100644 lib/layout/list/samples/assets/avatars/dude5.png create mode 100644 lib/layout/list/samples/assets/avatars/dude6.png create mode 100644 lib/layout/list/samples/assets/bg.png create mode 100644 lib/layout/list/samples/assets/item-hilite.png create mode 100644 lib/layout/list/samples/assets/pulldown.png create mode 100644 lib/layout/list/samples/assets/pullup.png create mode 100644 lib/layout/list/samples/assets/remove-icon.png create mode 100644 lib/layout/list/samples/assets/search-input-search.png create mode 100644 lib/layout/list/samples/assets/spinner.gif create mode 100644 lib/layout/list/samples/package.js create mode 100644 lib/layout/list/source/AlphaJumpList.js create mode 100644 lib/layout/list/source/AlphaJumper.css create mode 100644 lib/layout/list/source/AlphaJumper.js create mode 100644 lib/layout/list/source/AroundList.js create mode 100644 lib/layout/list/source/FlyweightRepeater.js create mode 100644 lib/layout/list/source/List.css create mode 100644 lib/layout/list/source/List.js create mode 100644 lib/layout/list/source/PulldownList.css create mode 100644 lib/layout/list/source/PulldownList.js create mode 100644 lib/layout/list/source/package.js create mode 100644 lib/layout/list/source/wip-package.js create mode 100644 lib/layout/package.js create mode 100644 lib/layout/panels/package.js create mode 100644 lib/layout/panels/samples/PanelsFlickrSample.css create mode 100644 lib/layout/panels/samples/PanelsFlickrSample.html create mode 100644 lib/layout/panels/samples/PanelsFlickrSample.js create mode 100644 lib/layout/panels/samples/PanelsSample.css create mode 100644 lib/layout/panels/samples/PanelsSample.html create mode 100644 lib/layout/panels/samples/PanelsSample.js create mode 100644 lib/layout/panels/samples/PanelsSlidingSample.css create mode 100644 lib/layout/panels/samples/PanelsSlidingSample.html create mode 100644 lib/layout/panels/samples/PanelsSlidingSample.js create mode 100644 lib/layout/panels/samples/assets/search-input-search.png create mode 100644 lib/layout/panels/samples/assets/spinner-large.gif create mode 100644 lib/layout/panels/samples/assets/spinner.gif create mode 100644 lib/layout/panels/samples/menutest.html create mode 100644 lib/layout/panels/samples/package.js create mode 100644 lib/layout/panels/source/Panels.css create mode 100644 lib/layout/panels/source/Panels.js create mode 100644 lib/layout/panels/source/arrangers/Arranger.css create mode 100644 lib/layout/panels/source/arrangers/Arranger.js create mode 100644 lib/layout/panels/source/arrangers/CardArranger.js create mode 100644 lib/layout/panels/source/arrangers/CardSlideInArranger.js create mode 100644 lib/layout/panels/source/arrangers/CarouselArranger.js create mode 100644 lib/layout/panels/source/arrangers/CollapsingArranger.js create mode 100644 lib/layout/panels/source/arrangers/DockRightArranger.js create mode 100644 lib/layout/panels/source/arrangers/OtherArrangers.js create mode 100644 lib/layout/panels/source/arrangers/package.js create mode 100644 lib/layout/panels/source/package.js create mode 100644 lib/layout/slideable/package.js create mode 100644 lib/layout/slideable/samples/SlideableSample.css create mode 100644 lib/layout/slideable/samples/SlideableSample.html create mode 100644 lib/layout/slideable/samples/SlideableSample.js create mode 100644 lib/layout/slideable/samples/package.js create mode 100644 lib/layout/slideable/source/Slideable.js create mode 100644 lib/layout/slideable/source/package.js create mode 100644 lib/layout/tree/package.js create mode 100644 lib/layout/tree/samples/TreeSample.css create mode 100644 lib/layout/tree/samples/TreeSample.html create mode 100644 lib/layout/tree/samples/TreeSample.js create mode 100644 lib/layout/tree/samples/assets/file.png create mode 100644 lib/layout/tree/samples/assets/folder-open.png create mode 100644 lib/layout/tree/samples/assets/folder.png create mode 100644 lib/layout/tree/samples/package.js create mode 100644 lib/layout/tree/source/Node.css create mode 100644 lib/layout/tree/source/Node.js create mode 100644 lib/layout/tree/source/package.js create mode 100644 lib/onyx/CONTRIBUTING md create mode 100644 lib/onyx/LICENSE-2.0.txt create mode 100644 lib/onyx/README.md create mode 100644 lib/onyx/css/Button.less create mode 100644 lib/onyx/css/ButtonColors.less create mode 100644 lib/onyx/css/Checkbox.less create mode 100644 lib/onyx/css/ContextualPopup.less create mode 100644 lib/onyx/css/DatePicker.less create mode 100644 lib/onyx/css/Grabber.less create mode 100644 lib/onyx/css/Groupbox.less create mode 100644 lib/onyx/css/Icon.less create mode 100644 lib/onyx/css/Input.less create mode 100644 lib/onyx/css/Item.less create mode 100644 lib/onyx/css/Menu.less create mode 100644 lib/onyx/css/MoreToolbar.less create mode 100644 lib/onyx/css/Picker.less create mode 100644 lib/onyx/css/Popup.less create mode 100644 lib/onyx/css/ProgressBar.less create mode 100644 lib/onyx/css/ProgressButton.less create mode 100644 lib/onyx/css/RadioButton.less create mode 100644 lib/onyx/css/RangeSlider.less create mode 100644 lib/onyx/css/RichText.less create mode 100644 lib/onyx/css/Scrim.less create mode 100644 lib/onyx/css/Slider.less create mode 100644 lib/onyx/css/Spinner.less create mode 100644 lib/onyx/css/TabButton.less create mode 100644 lib/onyx/css/TextArea.less create mode 100644 lib/onyx/css/TimePicker.less create mode 100644 lib/onyx/css/ToggleButton.less create mode 100644 lib/onyx/css/Toolbar.less create mode 100644 lib/onyx/css/Tooltip.less create mode 100644 lib/onyx/css/onyx-rules.less create mode 100644 lib/onyx/css/onyx-variables.less create mode 100644 lib/onyx/css/onyx.css create mode 100644 lib/onyx/css/onyx.less create mode 100644 lib/onyx/css/package.js create mode 100644 lib/onyx/deploy.bat create mode 100644 lib/onyx/deploy.sh create mode 100644 lib/onyx/design/inline-controlled.html create mode 100644 lib/onyx/design/inline.html create mode 100644 lib/onyx/design/menu-icon-bookmark.png create mode 100644 lib/onyx/design/toolbar-extended.html create mode 100644 lib/onyx/design/toolbar.html create mode 100644 lib/onyx/images/checkbox.png create mode 100644 lib/onyx/images/grabbutton.png create mode 100644 lib/onyx/images/gradient-invert.png create mode 100644 lib/onyx/images/gradient.png create mode 100644 lib/onyx/images/more.png create mode 100644 lib/onyx/images/progress-button-cancel.png create mode 100644 lib/onyx/images/search-input-cancel.png create mode 100644 lib/onyx/images/search-input-search.png create mode 100644 lib/onyx/images/slider-handle.png create mode 100644 lib/onyx/images/spinner-dark.gif create mode 100644 lib/onyx/images/spinner-light.gif create mode 100644 lib/onyx/package.js create mode 100644 lib/onyx/samples/ButtonGroupSample.html create mode 100644 lib/onyx/samples/ButtonGroupSample.js create mode 100644 lib/onyx/samples/ButtonSample.html create mode 100644 lib/onyx/samples/ButtonSample.js create mode 100644 lib/onyx/samples/CheckboxSample.html create mode 100644 lib/onyx/samples/CheckboxSample.js create mode 100644 lib/onyx/samples/ContextualPopupSample.html create mode 100644 lib/onyx/samples/ContextualPopupSample.js create mode 100644 lib/onyx/samples/DatePickerSample.html create mode 100644 lib/onyx/samples/DatePickerSample.js create mode 100644 lib/onyx/samples/DrawerSample.css create mode 100644 lib/onyx/samples/DrawerSample.html create mode 100644 lib/onyx/samples/DrawerSample.js create mode 100644 lib/onyx/samples/GroupboxSample.html create mode 100644 lib/onyx/samples/GroupboxSample.js create mode 100644 lib/onyx/samples/IconButtonSample.html create mode 100644 lib/onyx/samples/IconButtonSample.js create mode 100644 lib/onyx/samples/InputSample.html create mode 100644 lib/onyx/samples/InputSample.js create mode 100644 lib/onyx/samples/MenuSample.html create mode 100644 lib/onyx/samples/MenuSample.js create mode 100644 lib/onyx/samples/MoreToolbarSample.html create mode 100644 lib/onyx/samples/MoreToolbarSample.js create mode 100644 lib/onyx/samples/PickerSample.html create mode 100644 lib/onyx/samples/PickerSample.js create mode 100644 lib/onyx/samples/PopupSample.html create mode 100644 lib/onyx/samples/PopupSample.js create mode 100644 lib/onyx/samples/ProgressSample.html create mode 100644 lib/onyx/samples/ProgressSample.js create mode 100644 lib/onyx/samples/SliderSample.html create mode 100644 lib/onyx/samples/SliderSample.js create mode 100644 lib/onyx/samples/SpinnerSample.html create mode 100644 lib/onyx/samples/SpinnerSample.js create mode 100644 lib/onyx/samples/TimePickerSample.html create mode 100644 lib/onyx/samples/TimePickerSample.js create mode 100644 lib/onyx/samples/ToggleButtonSample.html create mode 100644 lib/onyx/samples/ToggleButtonSample.js create mode 100644 lib/onyx/samples/ToolbarSample.html create mode 100644 lib/onyx/samples/ToolbarSample.js create mode 100644 lib/onyx/samples/TooltipSample.html create mode 100644 lib/onyx/samples/TooltipSample.js create mode 100644 lib/onyx/samples/assets/favicon.ico create mode 100644 lib/onyx/samples/assets/fish_bowl.png create mode 100644 lib/onyx/samples/assets/menu-icon-bookmark.png create mode 100644 lib/onyx/samples/assets/search-input-search.png create mode 100644 lib/onyx/samples/package.js create mode 100644 lib/onyx/samples/sample.css create mode 100644 lib/onyx/source/Button.js create mode 100644 lib/onyx/source/Checkbox.js create mode 100644 lib/onyx/source/ContextualPopup.js create mode 100644 lib/onyx/source/DatePicker.js create mode 100644 lib/onyx/source/Drawer.js create mode 100644 lib/onyx/source/FlyweightPicker.js create mode 100644 lib/onyx/source/Grabber.js create mode 100644 lib/onyx/source/Groupbox.js create mode 100644 lib/onyx/source/Icon.js create mode 100644 lib/onyx/source/IconButton.js create mode 100644 lib/onyx/source/Input.js create mode 100644 lib/onyx/source/InputDecorator.js create mode 100644 lib/onyx/source/IntegerPicker.js create mode 100644 lib/onyx/source/Item.js create mode 100644 lib/onyx/source/Menu.js create mode 100644 lib/onyx/source/MenuDecorator.js create mode 100644 lib/onyx/source/MenuItem.js create mode 100644 lib/onyx/source/MoreToolbar.js create mode 100644 lib/onyx/source/Picker.js create mode 100644 lib/onyx/source/PickerButton.js create mode 100644 lib/onyx/source/PickerDecorator.js create mode 100644 lib/onyx/source/Popup.js create mode 100644 lib/onyx/source/ProgressBar.js create mode 100644 lib/onyx/source/ProgressButton.js create mode 100644 lib/onyx/source/RadioButton.js create mode 100644 lib/onyx/source/RadioGroup.js create mode 100644 lib/onyx/source/RangeSlider.js create mode 100644 lib/onyx/source/RichText.js create mode 100644 lib/onyx/source/Scrim.js create mode 100644 lib/onyx/source/Slider.js create mode 100644 lib/onyx/source/Spinner.js create mode 100644 lib/onyx/source/TabPanels.js create mode 100644 lib/onyx/source/TextArea.js create mode 100644 lib/onyx/source/TimePicker.js create mode 100644 lib/onyx/source/ToggleButton.js create mode 100644 lib/onyx/source/ToggleIconButton.js create mode 100644 lib/onyx/source/Toolbar.js create mode 100644 lib/onyx/source/Tooltip.js create mode 100644 lib/onyx/source/TooltipDecorator.js create mode 100644 lib/onyx/source/design.js create mode 100644 lib/onyx/source/package.js create mode 100644 lib/onyx/source/wip-package.js create mode 100644 source/Scheduler.css create mode 100644 source/Scheduler.js create mode 100644 source/Theme.less create mode 100644 source/function/calendar.css create mode 100644 source/function/calendar.js create mode 100644 source/function/package.js create mode 100644 source/function/to_do.css create mode 100644 source/function/to_do.js create mode 100644 source/function/weekly.css create mode 100644 source/function/weekly.js create mode 100644 source/package.js create mode 100644 tools/deploy.bat create mode 100644 tools/deploy.sh diff --git a/README-CORDOVA-WEBOS.md b/README-CORDOVA-WEBOS.md new file mode 100644 index 0000000..8ecabdc --- /dev/null +++ b/README-CORDOVA-WEBOS.md @@ -0,0 +1,8 @@ +Cordova webOS Instructions: +--------------------------- + +- Set up your project the same way you would set up any other bootplate project. +- Modify your index.html and JavaScript files as outlined in this blog post: [JavaScript Apps for Open webOS With Enyo and Cordova](http://blog.openwebosproject.org/post/39278618299/javascript-apps-for-open-webos-with-enyo-and-cordova) +- Copy appinfo.json from the PhoneGap 'lib/webos/framework' directory and a cordova JavaScript file from the PhoneGap 'lib/webos/lib' directory +- Modify appinfo.json for your project and add an icon +- run tools\deploy.bat --cordova-webos or tools/deploy.sh --cordova-webos to deploy your app. diff --git a/README.md b/README.md index 828a527..ae66288 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,4 @@ -### About the Enyo Community Gallery ### +scheduler +========= -We are really excited by the amount of collaboration and sharing happening in the [Enyo Forums](http://forums.enyojs.com/). This initial release of the [Enyo Community Gallery](http://enyojs.com/gallery) is a first step at providing a way to showcase and discover new Enyo add-on components and libraries developed by the community. There are many directions we can go with this, such as categorization and dependency management, but for now we wanted to get something barebones out quickly to capture all of the great work being produced by the community. - -Those interested in sharing their Enyo components, samples, etc. are encouraged to follow these instructions for getting their components showcased in the gallery. - -### Directions for Adding Components to Gallery ### - -The gallery is a simple Enyo app hosted from our github repo. To register a new component please follow these instructions: - -1. Fork the github repo (`git@github.com:enyojs/gallery.git`) -2. Edit the gallery_manifest.json file to add author and component info (see below) -3. If you want, add a line to the noscript part of index.html for your component. -4. Add a 200 x 200 px image/screenshot for your component to the gallery_images directory. - It should be JPEG and named with your component's unique component ID, e.g. `me.awesomecontrol.jpg`. -5. Commit your changes to your fork -6. Submit a github pull request to the `gh-pages` branch of `enyojs/gallery` - -The format of gallery_manifest.json is as follows: - - "owners": { // List of authors, referenced by component descriptions - "xxxx": { // Author id (github username) - "name": "", // Display name for author - "website": "", // Author's website - "twitter": "" // Author's twitter handle - }, - ... - } - "widgets": [ // The list of components in the gallery - { - "name": "", // Unique component id (owner.component) - "displayName": "", // Display name for component - "owner": "xxxx", // Author id, from above - "dependencies": [ // List of libraries this component requires - { - "name": "", // Name of dependency - "version": "" // Version of dependency - }, - ... - ], - "url": "", // URL to source code (i.e. github link) - "demoUrl": "", // URL to demo website (optional) - "submissionDate": "", // Date of submission (i.e. "Mar 26, 2012") - "testedPlatforms": "", // List of platforms this component was tested on - "license": "", // Reference to standard license (i.e. "Apache 2.0" or license text) - "version": "1", // Version of this component (optional) - "blurb": "" // Description of component - }, - ... - ] - - -Please note the following: - -* We will only accept pull requests to the catalog for OSS-licensed components from the original author. If you have forked another member's component please submit a separate, new component. -* There should be one unique "owner" entry per author. For the owner id please use your github username. You may choose your full name or username as the display name. -* The "website", "twitter", and "demoUrl" fields are optional and may be omitted if you wish. -* The "testedPlatforms" field should list the platforms you have tested your component on (i.e. "iOS 5.1", "Chrome 18", "IE9"). -* The "license" field should either reference a standard OSS license (i.e. "Apache 2.0") or include the text of your license. -* The "dependencies" field should list any other Enyo libraries your component requires (i.e. onyx, layout). -* The "version" field for dependencies is optional but will be displayed if present. -* You may include a "version" for your component, however we are not yet using this on the site. -* New entries in the index.html file should follow the format having a link to the gallery entry and the control name. +enyo scheduler application diff --git a/api/assets/busy.gif b/api/assets/busy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dba81f5113f127557dfdfad9ad5208bfd694c322 GIT binary patch literal 310 zcmZ?wbhEHbf=ZVnkn}S!FamXRfb`2GSO_27H%%Z}3|T)5P&Y_F z7fW06NtuTW1agq185!7NwzIS;CkZcfsalC-I12+zHxJMwD|QRAF)({oae<8I1pAa7 SVf&P{#ZrcQ86=8C7_0#!o;rsB literal 0 HcmV?d00001 diff --git a/api/assets/favicon.ico b/api/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..52c86347fe3e10042c05374362757fa260307d50 GIT binary patch literal 1150 zcmb`FKMnyw7{#BEC=@o4NK}++2k<9R=-ogfBntOXlHdvyYK=~#aR8MgC>3JNvw6v6 zt=*BB&9}4j&HUcH{bqoSeS!e?UBfsBlmXOj*p$tLdE23F=SqbzI8JMq)4}u`6~jJl zZFFAje9-(^L+ot9~P>KuLiljZ#*X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/api/build/app.css b/api/build/app.css new file mode 100644 index 0000000..0e6a0bd --- /dev/null +++ b/api/build/app.css @@ -0,0 +1,889 @@ + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/fittable/source/FittableLayout.css */ + +.enyo-fittable-rows-layout { + position: relative; +} + +.enyo-fittable-rows-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + /* float when not stretched */ + float: left; + clear: both; +} + +/* non-floating when stretched */ +.enyo-fittable-rows-layout.enyo-stretch > * { + float: none; + clear: none; +} + +/* setting to enforce margin collapsing */ +/* NOTE: rows cannot have margin left/right */ +.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { + float: left; + clear: both; + width: 100%; + /* note: harsh resets */ + margin-left: 0 !important; + margin-right: 0 !important; +} + +.enyo-fittable-columns-layout { + position: relative; + text-align: left; + white-space: nowrap; +} + +.enyo-fittable-columns-layout.enyo-center { + text-align: center; +} + +.enyo-fittable-columns-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + vertical-align: top; + display: inline-block; + white-space: normal; +} + +.enyo-fittable-columns-layout.enyo-tool-decorator > * { + vertical-align: middle; +} + +/* repair clobbered white-space setting for pre, code */ +.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { + white-space: pre; +} + +.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { + white-space: nowrap; +} + +/* NOTE: columns cannot have margin top/bottom */ +.enyo-fittable-columns-layout.enyo-stretch > * { + height: 100%; + /* note: harsh resets */ + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/list/source/List.css */ + +.enyo-list { + position: relative; +} + +.enyo-list-port { + overflow: hidden; + position: relative; + height: 1000000px; +} + +.enyo-list-page, .enyo-list-holdingarea { + position: absolute; + left: 0; + right: 0; +} + +.enyo-list-holdingarea { + top: -10000px; +} + +.enyo-pinned-list-placeholder { + border: 1px solid red; + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-pinned-list-placeholder button { + width: 100px; height: 100%; + position: absolute; + top: 0; right: 0; +} + +.enyo-list-reorder-container { + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-animatedTopAndLeft { + -webkit-transition: top 0.1s linear, left 0.1s linear; + -moz-transition: top 0.1s linear, left 0.1s linear; + -o-transition: top 0.1s linear, left 0.1s linear; + transition: top 0.1s linear, left 0.1s linear; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/list/source/PulldownList.css */ + +.enyo-list-pulldown { + position: absolute; + bottom: 100%; + left: 0; + right: 0; +} + +.enyo-puller { + position: relative; + height: 50px; + font-size: 22px; + color: #444; + padding: 20px 0 0px 34px; +} + +.enyo-puller-text { + position: absolute; + left: 80px; + top: 22px; +} + +.enyo-puller-arrow { + position: relative; + background: #444; + width: 7px; + height: 28px; + transition: transform 0.3s; + -webkit-transition: -webkit-transform 0.3s; + -moz-transition: -moz-transform 0.3s; + -o-transition: -o-transform 0.3s; + -ms-transition: -ms-transform 0.3s; +} + +.enyo-puller-arrow:after { + content: " "; + height: 0; + width: 0; + position: absolute; + border: 10px solid transparent; + border-bottom-color: #444; + bottom: 100%; + left: 50%; + margin-left: -10px; +} + +.enyo-puller-arrow-up { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); +} + +.enyo-puller-arrow-down { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); + -ms-transform: rotate(180deg); +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/panels/source/arrangers/Arranger.css */ + +.enyo-arranger { + position: relative; + overflow: hidden; +} + +.enyo-arranger.enyo-fit { + position: absolute; +} + +.enyo-arranger > * { + position: absolute; + left: 0; + top: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.enyo-arranger-fit > * { + /* override any width/height set on panels */ + width: 100% !important; + height: 100% !important; + min-width: 0 !important; + min-height: 0 !important; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/panels/source/Panels.css */ + +.enyo-panels { +} + +.enyo-panels-fit-narrow { +} + +@media all and (max-width: 800px) { + .enyo-panels-fit-narrow > * { + min-width: 100%; + max-width: 100%; + } +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/tree/source/Node.css */ + +.enyo-node { + cursor: default; + padding: 4px; +} + +.enyo-node img { + vertical-align: middle; + padding-right: 6px; +} + +.enyo-node-box { + overflow: hidden; +} + +.enyo-node-client { + position: relative; +} + +.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { + -ms-transition-property: height, top; + -ms-transition-duration: 0.2s, 0.2s; + -moz-transition-property: height, top; + -moz-transition-duration: 0.2s, 0.2s; + -o-transition-property: height, top; + -o-transition-duration: 0.2s, 0.2s; + -webkit-transition-property: height, top; + -webkit-transition-duration: 0.2s, 0.2s; + transition-property: height, top; + transition-duration: 0.2s, 0.2s; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/imageview/source/ImageViewPin.css */ + + +.pinDebug { + background:yellow; + border:1px solid yellow; +} + +/* ../source/foss/syntaxhighlighter_3.0.83_fork/sh-min.css */ + + +/* styles/shCoreEclipse.css */ + +/** + * SyntaxHighlighter + * http://alexgorbatchev.com/SyntaxHighlighter + * + * SyntaxHighlighter is donationware. If you are using it, please donate. + * http://alexgorbatchev.com/SyntaxHighlighter/donate.html + * + * @version + * 3.0.83 (July 02 2010) + * + * @copyright + * Copyright (C) 2004-2010 Alex Gorbatchev. + * + * @license + * Dual licensed under the MIT and GPL licenses. + */ +.syntaxhighlighter a, +.syntaxhighlighter div, +.syntaxhighlighter code, +.syntaxhighlighter table, +.syntaxhighlighter table td, +.syntaxhighlighter table tr, +.syntaxhighlighter table tbody, +.syntaxhighlighter table thead, +.syntaxhighlighter table caption, +.syntaxhighlighter textarea { + -moz-border-radius: 0 0 0 0 !important; + -webkit-border-radius: 0 0 0 0 !important; + background: none !important; + border: 0 !important; + bottom: auto !important; + float: none !important; + height: auto !important; + left: auto !important; + line-height: 1.1em !important; + margin: 0 !important; + outline: 0 !important; + overflow: visible !important; + padding: 0 !important; + position: static !important; + right: auto !important; + text-align: left !important; + top: auto !important; + vertical-align: baseline !important; + width: auto !important; + box-sizing: content-box !important; + font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; + font-weight: normal !important; + font-style: normal !important; + font-size: 1em !important; + min-height: inherit !important; + min-height: auto !important; +} + +.syntaxhighlighter { + width: 100% !important; + margin: 1em 0 1em 0 !important; + position: relative !important; + overflow: auto !important; + font-size: 1em !important; +} +.syntaxhighlighter.source { + overflow: hidden !important; +} +.syntaxhighlighter .bold { + font-weight: bold !important; +} +.syntaxhighlighter .italic { + font-style: italic !important; +} +.syntaxhighlighter .line { + white-space: pre !important; +} +.syntaxhighlighter table { + width: 100% !important; +} +.syntaxhighlighter table caption { + text-align: left !important; + padding: .5em 0 0.5em 1em !important; +} +.syntaxhighlighter table td.code { + width: 100% !important; +} +.syntaxhighlighter table td.code .container { + position: relative !important; +} +.syntaxhighlighter table td.code .container textarea { + box-sizing: border-box !important; + position: absolute !important; + left: 0 !important; + top: 0 !important; + width: 100% !important; + height: 100% !important; + border: none !important; + background: white !important; + padding-left: 1em !important; + overflow: hidden !important; + white-space: pre !important; +} +.syntaxhighlighter table td.gutter .line { + text-align: right !important; + padding: 0 0.5em 0 1em !important; +} +.syntaxhighlighter table td.code .line { + padding: 0 1em !important; +} +.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line { + padding-left: 0em !important; +} +.syntaxhighlighter.show { + display: block !important; +} +.syntaxhighlighter.collapsed table { + display: none !important; +} +.syntaxhighlighter.collapsed .toolbar { + padding: 0.1em 0.8em 0em 0.8em !important; + font-size: 1em !important; + position: static !important; + width: auto !important; + height: auto !important; +} +.syntaxhighlighter.collapsed .toolbar span { + display: inline !important; + margin-right: 1em !important; +} +.syntaxhighlighter.collapsed .toolbar span a { + padding: 0 !important; + display: none !important; +} +.syntaxhighlighter.collapsed .toolbar span a.expandSource { + display: inline !important; +} +.syntaxhighlighter .toolbar { + position: absolute !important; + right: 1px !important; + top: 1px !important; + width: 11px !important; + height: 11px !important; + font-size: 10px !important; + z-index: 10 !important; +} +.syntaxhighlighter .toolbar span.title { + display: inline !important; +} +.syntaxhighlighter .toolbar a { + display: block !important; + text-align: center !important; + text-decoration: none !important; + padding-top: 1px !important; +} +.syntaxhighlighter .toolbar a.expandSource { + display: none !important; +} +.syntaxhighlighter.ie { + font-size: .9em !important; + padding: 1px 0 1px 0 !important; +} +.syntaxhighlighter.ie .toolbar { + line-height: 8px !important; +} +.syntaxhighlighter.ie .toolbar a { + padding-top: 0px !important; +} +.syntaxhighlighter.printing .line.alt1 .content, +.syntaxhighlighter.printing .line.alt2 .content, +.syntaxhighlighter.printing .line.highlighted .number, +.syntaxhighlighter.printing .line.highlighted.alt1 .content, +.syntaxhighlighter.printing .line.highlighted.alt2 .content { + background: none !important; +} +.syntaxhighlighter.printing .line .number { + color: #bbbbbb !important; +} +.syntaxhighlighter.printing .line .content { + color: black !important; +} +.syntaxhighlighter.printing .toolbar { + display: none !important; +} +.syntaxhighlighter.printing a { + text-decoration: none !important; +} +.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a { + color: black !important; +} +.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a { + color: #008200 !important; +} +.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a { + color: blue !important; +} +.syntaxhighlighter.printing .keyword { + color: #006699 !important; + font-weight: bold !important; +} +.syntaxhighlighter.printing .preprocessor { + color: gray !important; +} +.syntaxhighlighter.printing .variable { + color: #aa7700 !important; +} +.syntaxhighlighter.printing .value { + color: #009900 !important; +} +.syntaxhighlighter.printing .functions { + color: #ff1493 !important; +} +.syntaxhighlighter.printing .constants { + color: #0066cc !important; +} +.syntaxhighlighter.printing .script { + font-weight: bold !important; +} +.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a { + color: gray !important; +} +.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a { + color: #ff1493 !important; +} +.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a { + color: red !important; +} +.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a { + color: black !important; +} + +.syntaxhighlighter { + background-color: white !important; +} +.syntaxhighlighter .line.alt1 { + background-color: white !important; +} +.syntaxhighlighter .line.alt2 { + background-color: white !important; +} +.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 { + background-color: #c3defe !important; +} +.syntaxhighlighter .line.highlighted.number { + color: white !important; +} +.syntaxhighlighter table caption { + color: black !important; +} +.syntaxhighlighter .gutter { + color: #787878 !important; +} +.syntaxhighlighter .gutter .line { + border-right: 3px solid #d4d0c8 !important; +} +.syntaxhighlighter .gutter .line.highlighted { + background-color: #d4d0c8 !important; + color: white !important; +} +.syntaxhighlighter.printing .line .content { + border: none !important; +} +.syntaxhighlighter.collapsed { + overflow: visible !important; +} +.syntaxhighlighter.collapsed .toolbar { + color: #3f5fbf !important; + background: white !important; + border: 1px solid #d4d0c8 !important; +} +.syntaxhighlighter.collapsed .toolbar a { + color: #3f5fbf !important; +} +.syntaxhighlighter.collapsed .toolbar a:hover { + color: #aa7700 !important; +} +.syntaxhighlighter .toolbar { + color: #a0a0a0 !important; + background: #d4d0c8 !important; + border: none !important; +} +.syntaxhighlighter .toolbar a { + color: #a0a0a0 !important; +} +.syntaxhighlighter .toolbar a:hover { + color: red !important; +} +.syntaxhighlighter .plain, .syntaxhighlighter .plain a { + color: black !important; +} +.syntaxhighlighter .comments, .syntaxhighlighter .comments a { + color: #3f5fbf !important; +} +.syntaxhighlighter .string, .syntaxhighlighter .string a { + color: #2a00ff !important; +} +.syntaxhighlighter .keyword { + color: #7f0055 !important; +} +.syntaxhighlighter .preprocessor { + color: #646464 !important; +} +.syntaxhighlighter .variable { + color: #aa7700 !important; +} +.syntaxhighlighter .value { + color: #009900 !important; +} +.syntaxhighlighter .functions { + color: #ff1493 !important; +} +.syntaxhighlighter .constants { + color: #0066cc !important; +} +.syntaxhighlighter .script { + font-weight: bold !important; + color: #7f0055 !important; + background-color: none !important; +} +.syntaxhighlighter .color1, .syntaxhighlighter .color1 a { + color: gray !important; +} +.syntaxhighlighter .color2, .syntaxhighlighter .color2 a { + color: #ff1493 !important; +} +.syntaxhighlighter .color3, .syntaxhighlighter .color3 a { + color: red !important; +} + +.syntaxhighlighter .keyword { + font-weight: bold !important; +} +.syntaxhighlighter .xml .keyword { + color: #3f7f7f !important; + font-weight: normal !important; +} +.syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a { + color: #7f007f !important; +} +.syntaxhighlighter .xml .string { + font-style: italic !important; + color: #2a00ff !important; +} + + +/* patch.css */ + +.syntaxhighlighter { + overflow: visible !important; +} + + + +/* ../source/App.css */ + +.tab { + background: whitesmoke; + border: 1px dotted silver; + padding: 6px; + margin: 0; +} + +.tab.active { + background: lightblue; +} + +.input-decorator { + padding: 6px 8px 10px 8px; + border-radius: 3px; + border: 1px solid; + border-color: rgba(0,0,0,0.1); + margin: 0; +} + +.input-decorator > input { + /* reset */ + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + font-size: 120%; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + /* -webkit-appearance: caret;*/ +} + +.packages-editor { + background: lightgrey; + padding: 20px; + border-radius: 8px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); +} + +#app_left { + width: 350px; + border: 1px solid orange; +} + +#app_left_tabs { + background: #eee; + font-size: 120%; +} + +#app_kinds { + padding: 8px; + font-size: 140%; +} + +#app_index { + padding: 8px; + font-size: 120%; +} + +#app_modules { + padding: 8px; + font-size: 140%; +} + +#app_packages { + padding: 8px; + font-size: 140%; +} + +#app_doc { + padding: 8px 8px; +} + +#app_scope { + padding: 8px; + border-bottom: 1px dotted silver; +} + +#app_header { + padding: 8px; +} + +#app_tocFrame { + white-space: nowrap; +} + +#app_toc { +} + +#app_bodyFrame { +} + +#app_body { + padding: 8px; +} + +/* ../source/presentation.css */ + +blockquote { + margin-top: 0; + margin-bottom: 0; +} + +blockquote hr { + border: 0; +} + +hr { + border-style: dotted; + border-bottom-style: none; + border-color: #ccc; +} + +a { + text-decoration: none; + border-bottom: 1px dotted lightblue; + color: #3B5982; + line-height: 1.3em; +} + +a:hover { + text-decoration: none; + text-shadow: 0 0 2px orange; + -webkit-transition: text-shadow 0.5s; + -moz-transition: text-shadow 0.5s; + -o-transition: text-shadow 0.5s; + -ms-transition: text-shadow 0.5s; +} + +/* +a { + text-decoration: none; + background-color: #ddd; + padding: 3px 8px; + border-radius: 12px; + line-height: 2em; + color: #333; +} + +a:hover { + background-color: lightblue; + -webkit-transition: background-color 0.5s; +} +*/ + +comment { + /*border-left: 2px dotted silver;*/ + background: whitesmoke; + display: block; + padding: 4px 0 4px 12px; + margin: 16px 0 4px; + /* + font-size: small; + padding: 8px; + font-style: italic; + color: green; + padding: 16px 0 8px; + */ +} + +label { + font-weight: bold; + color: #D38628; +} + +public { + color: Orange; + padding-right: 6px; + display: none; +} + +protected { + color: Red; + padding-right: 6px; +} + +published { + color: green; + padding-right: 6px; +} + +kind { + font-size: 130%; + font-weight: bold; + display: block; +} + +package { + color: black; + background-color: #B0E0E6; + font-size: 90%; + padding: 3pt; + float: right; +} + +moduleName { + font-size: 130%; + font-weight: bold; + display: block; +} + +superkind { + color: #555; + display: block; +} + +prototype { + font-style: italic; + /* + font-size: small; + color: blue; + */ + color: #888; +} + +module { + text-decoration: underline; + color: #C39; + cursor: pointer; +} + +topic { + /* + font-weight: bold; + text-decoration: underline; + color: #46E; + cursor: pointer; + */ +} + +column { + display: inline-block; + font-size: small; + padding: 16px; + /*border-right: 1px dotted silver;*/ + vertical-align: top; +} + +divider { + display: block; + color: #0D0D0D; + font-size: 120%; + font-weight: bold; + margin-left: -1px; + margin-top: 1em; + margin-bottom: 5px; + /*border-bottom: 1px dotted silver;*/ +} + +code { + background-color: white; + padding: 2px; +} + +arguments { + color: purple; +} + diff --git a/api/build/app.js b/api/build/app.js new file mode 100644 index 0000000..532b618 --- /dev/null +++ b/api/build/app.js @@ -0,0 +1,4372 @@ + +// minifier: path aliases + +enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/"}); + +// FittableLayout.js + +enyo.kind({ +name: "enyo.FittableLayout", +kind: "Layout", +calcFitIndex: function() { +for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; +}, +getFitControl: function() { +var e = this.container.children, t = e[this.fitIndex]; +return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; +}, +getLastControl: function() { +var e = this.container.children, t = e.length - 1, n = e[t]; +while ((n = e[t]) && !n.showing) t--; +return n; +}, +_reflow: function(e, t, n, r) { +this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); +var i = this.getFitControl(); +if (!i) return; +var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); +f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); +var l = i.getBounds(); +o = l[n] - (a && a[n] || 0); +var c = this.getLastControl(); +if (c) { +var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; +if (c != i) { +var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; +u = v - d; +} else u = h; +} +var m = s - (o + u); +i.applyStyle(e, m + "px"); +}, +reflow: function() { +this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); +} +}), enyo.kind({ +name: "enyo.FittableColumnsLayout", +kind: "FittableLayout", +orient: "h", +layoutClass: "enyo-fittable-columns-layout" +}), enyo.kind({ +name: "enyo.FittableRowsLayout", +kind: "FittableLayout", +layoutClass: "enyo-fittable-rows-layout", +orient: "v" +}); + +// FittableRows.js + +enyo.kind({ +name: "enyo.FittableRows", +layoutKind: "FittableRowsLayout", +noStretch: !1 +}); + +// FittableColumns.js + +enyo.kind({ +name: "enyo.FittableColumns", +layoutKind: "FittableColumnsLayout", +noStretch: !1 +}); + +// FlyweightRepeater.js + +enyo.kind({ +name: "enyo.FlyweightRepeater", +published: { +count: 0, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +clientClasses: "", +clientStyle: "", +rowOffset: 0 +}, +events: { +onSetupItem: "", +onRenderRow: "" +}, +bottomUp: !1, +components: [ { +kind: "Selection", +onSelect: "selectDeselect", +onDeselect: "selectDeselect" +}, { +name: "client" +} ], +create: function() { +this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); +}, +noSelectChanged: function() { +this.noSelect && this.$.selection.clear(); +}, +multiSelectChanged: function() { +this.$.selection.setMulti(this.multiSelect); +}, +clientClassesChanged: function() { +this.$.client.setClasses(this.clientClasses); +}, +clientStyleChanged: function() { +this.$.client.setStyle(this.clientStyle); +}, +setupItem: function(e) { +this.doSetupItem({ +index: e, +selected: this.isSelected(e) +}); +}, +generateChildHtml: function() { +var e = ""; +this.index = null; +for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); +return e; +}, +previewDomEvent: function(e) { +var t = this.index = this.rowForEvent(e); +e.rowIndex = e.index = t, e.flyweight = this; +}, +decorateEvent: function(e, t, n) { +var r = t && t.index != null ? t.index : this.index; +t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); +}, +tap: function(e, t) { +if (this.noSelect || t.index === -1) return; +this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); +}, +selectDeselect: function(e, t) { +this.renderRow(t.key); +}, +getSelection: function() { +return this.$.selection; +}, +isSelected: function(e) { +return this.getSelection().isSelected(e); +}, +renderRow: function(e) { +if (e < this.rowOffset || e >= this.count + this.rowOffset) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ +rowIndex: e +})); +}, +fetchRowNode: function(e) { +if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); +}, +rowForEvent: function(e) { +if (!this.hasNode()) return -1; +var t = e.target; +while (t && t !== this.node) { +var n = t.getAttribute && t.getAttribute("data-enyo-index"); +if (n !== null) return Number(n); +t = t.parentNode; +} +return -1; +}, +prepareRow: function(e) { +if (e < 0 || e >= this.count) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +enyo.FlyweightRepeater.claimNode(this.$.client, t); +}, +lockRow: function() { +this.$.client.teardownChildren(); +}, +performOnRow: function(e, t, n) { +if (e < 0 || e >= this.count) return; +t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); +}, +statics: { +claimNode: function(e, t) { +var n; +t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); +for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); +} +} +}); + +// List.js + +enyo.kind({ +name: "enyo.List", +kind: "Scroller", +classes: "enyo-list", +published: { +count: 0, +rowsPerPage: 50, +bottomUp: !1, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +fixedHeight: !1, +reorderable: !1, +centerReorderContainer: !0, +reorderComponents: [], +pinnedReorderComponents: [], +swipeableComponents: [], +enableSwipe: !1, +persistSwipeableItem: !1 +}, +events: { +onSetupItem: "", +onSetupReorderComponents: "", +onSetupPinnedReorderComponents: "", +onReorder: "", +onSetupSwipeItem: "", +onSwipeDrag: "", +onSwipe: "", +onSwipeComplete: "" +}, +handlers: { +onAnimateFinish: "animateFinish", +onRenderRow: "rowRendered", +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onup: "up", +onholdpulse: "holdpulse" +}, +rowHeight: 0, +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0;" +} ] +} ], +reorderHoldTimeMS: 600, +draggingRowIndex: -1, +draggingRowNode: null, +placeholderRowIndex: -1, +dragToScrollThreshold: .1, +prevScrollTop: 0, +autoScrollTimeoutMS: 20, +autoScrollTimeout: null, +autoscrollPageY: 0, +pinnedReorderMode: !1, +initialPinPosition: -1, +itemMoved: !1, +currentPageNumber: -1, +completeReorderTimeout: null, +swipeIndex: null, +swipeDirection: null, +persistentItemVisible: !1, +persistentItemOrigin: null, +swipeComplete: !1, +completeSwipeTimeout: null, +completeSwipeDelayMS: 500, +normalSwipeSpeedMS: 200, +fastSwipeSpeedMS: 100, +percentageDraggedThreshold: .2, +importProps: function(e) { +e && e.reorderable && (this.touch = !0), this.inherited(arguments); +}, +create: function() { +this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); +}, +initComponents: function() { +this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); +}, +createReorderTools: function() { +this.createComponent({ +name: "reorderContainer", +classes: "enyo-list-reorder-container", +ondown: "sendToStrategy", +ondrag: "sendToStrategy", +ondragstart: "sendToStrategy", +ondragfinish: "sendToStrategy", +onflick: "sendToStrategy" +}); +}, +createStrategy: function() { +this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); +}, +createSwipeableComponents: function() { +for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { +owner: this.owner +}); +}, +rendered: function() { +this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); +}, +resizeHandler: function() { +this.inherited(arguments), this.refresh(); +}, +bottomUpChanged: function() { +this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); +}, +noSelectChanged: function() { +this.$.generator.setNoSelect(this.noSelect); +}, +multiSelectChanged: function() { +this.$.generator.setMultiSelect(this.multiSelect); +}, +toggleSelectedChanged: function() { +this.$.generator.setToggleSelected(this.toggleSelected); +}, +countChanged: function() { +this.hasNode() && this.updateMetrics(); +}, +sendToStrategy: function(e, t) { +this.$.strategy.dispatchEvent("on" + t.type, t, e); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +holdpulse: function(e, t) { +if (!this.getReorderable() || this.isReordering()) return; +if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; +}, +dragstart: function(e, t) { +if (this.isReordering()) return !0; +if (this.isSwipeable()) return this.swipeDragStart(e, t); +}, +drag: function(e, t) { +if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; +if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; +}, +dragfinish: function(e, t) { +this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); +}, +up: function(e, t) { +this.isReordering() && this.finishReordering(e, t); +}, +generatePage: function(e, t) { +this.page = e; +var n = this.rowsPerPage * this.page; +this.$.generator.setRowOffset(n); +var r = Math.min(this.count - n, this.rowsPerPage); +this.$.generator.setCount(r); +var i = this.$.generator.generateChildHtml(); +t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); +var s = t.getBounds().height; +!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); +if (!this.fixedHeight) { +var o = this.getPageHeight(e); +this.pageHeights[e] = s, this.portSize += s - o; +} +}, +pageForRow: function(e) { +return Math.floor(e / this.rowsPerPage); +}, +preserveDraggingRowNode: function(e) { +this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); +}, +update: function(e) { +var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; +this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); +}, +getPageRowHeights: function(e) { +var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); +for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { +height: s.height, +width: s.width +}); +return t; +}, +updateRowBounds: function(e) { +this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); +}, +updateRowBoundsAtIndex: function(e, t, n) { +var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); +t[e].height = i.height, t[e].width = i.width; +}, +updateForPosition: function(e) { +this.update(this.calcPos(e)); +}, +calcPos: function(e) { +return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; +}, +adjustBottomPage: function() { +var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; +this.positionPage(e.pageNo, e); +}, +adjustPortSize: function() { +this.scrollerHeight = this.getBounds().height; +var e = Math.max(this.scrollerHeight, this.portSize); +this.$.port.applyStyle("height", e + "px"); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e); +t.applyStyle(this.pageBound, n + "px"); +}, +pageToPosition: function(e) { +var t = 0, n = e; +while (n > 0) n--, t += this.getPageHeight(n); +return t; +}, +positionToPageInfo: function(e) { +var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; +while (n >= 0) t++, r = this.getPageHeight(t), n -= r; +return t = Math.max(t, 0), { +no: t, +height: r, +pos: n + r, +startRow: t * this.rowsPerPage, +endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) +}; +}, +isPageInRange: function(e) { +return e == Math.max(0, Math.min(this.pageCount - 1, e)); +}, +getPageHeight: function(e) { +var t = this.pageHeights[e]; +if (!t) { +var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); +t = this.defaultPageHeight * (r / this.rowsPerPage); +} +return Math.max(1, t); +}, +invalidatePages: function() { +this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); +}, +invalidateMetrics: function() { +this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); +}, +scroll: function(e, t) { +var n = this.inherited(arguments), r = this.getScrollTop(); +return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); +}, +setScrollTop: function(e) { +this.update(e), this.inherited(arguments), this.twiddle(); +}, +getScrollPosition: function() { +return this.calcPos(this.getScrollTop()); +}, +setScrollPosition: function(e) { +this.setScrollTop(this.calcPos(e)); +}, +scrollToBottom: function() { +this.update(this.getScrollBounds().maxTop), this.inherited(arguments); +}, +scrollToRow: function(e) { +var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); +this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); +if (t == this.p0 || t == this.p1) { +var i = this.$.generator.fetchRowNode(e); +if (i) { +var s = i.offsetTop; +this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); +var o = this.getScrollPosition() + s; +this.setScrollPosition(o); +} +} +}, +scrollToStart: function() { +this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); +}, +scrollToEnd: function() { +this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); +}, +refresh: function() { +this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); +}, +reset: function() { +this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); +}, +getSelection: function() { +return this.$.generator.getSelection(); +}, +select: function(e, t) { +return this.getSelection().select(e, t); +}, +deselect: function(e) { +return this.getSelection().deselect(e); +}, +isSelected: function(e) { +return this.$.generator.isSelected(e); +}, +renderRow: function(e) { +this.$.generator.renderRow(e); +}, +rowRendered: function(e, t) { +this.updateRowBounds(t.rowIndex); +}, +prepareRow: function(e) { +this.$.generator.prepareRow(e); +}, +lockRow: function() { +this.$.generator.lockRow(); +}, +performOnRow: function(e, t, n) { +this.$.generator.performOnRow(e, t, n); +}, +animateFinish: function(e) { +return this.twiddle(), !0; +}, +twiddle: function() { +var e = this.getStrategy(); +enyo.call(e, "twiddle"); +}, +pageForPageNumber: function(e, t) { +return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; +}, +shouldStartReordering: function(e, t) { +return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; +}, +startReordering: function(e) { +this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); +}, +buildReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +styleReorderContainer: function(e) { +this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); +}, +appendNodeToReorderContainer: function(e) { +this.$.reorderContainer.createComponent({ +allowHtml: !0, +content: e.innerHTML +}).render(); +}, +centerReorderContainerOnPointer: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; +this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); +}, +positionReorderContainer: function(e, t) { +this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); +}, +setPositionReorderContainerTimeout: function() { +this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { +this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); +}), 100); +}, +clearPositionReorderContainerTimeout: function() { +this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); +}, +shouldDoReorderDrag: function() { +return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; +}, +reorderDrag: function(e) { +this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); +}, +updatePlaceholderPosition: function(e) { +var t = this.getRowIndexFromCoordinate(e); +t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); +}, +positionReorderNode: function(e) { +var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; +r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); +}, +checkForAutoScroll: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; +this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); +}, +stopAutoScrolling: function() { +this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); +}, +startAutoScrolling: function() { +this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); +}, +autoScroll: function() { +this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ +ddx: 0, +ddy: 0 +}), this.updatePlaceholderPosition(this.autoscrollPageY); +}, +movePlaceholderToIndex: function(e) { +var t, n; +if (e < 0) return; +e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); +var r = this.pageForRow(e); +r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; +}, +finishReordering: function(e, t) { +if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; +return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; +}, +moveReorderedContainerToDroppedPosition: function() { +var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); +this.positionReorderContainer(n, t); +}, +completeFinishReordering: function(e) { +this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); +if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { +this.beginPinnedReorder(e); +return; +} +this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); +}, +beginPinnedReorder: function(e) { +this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { +index: this.draggingRowIndex +})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; +}, +emptyAndHideReorderContainer: function() { +this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); +}, +buildPinnedReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +reorderRows: function(e) { +this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); +}, +makeReorderEvent: function(e) { +return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; +}, +positionReorderedNode: function() { +if (!this.removedInitialPage) { +var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); +e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; +if (this.currentPageNumber != this.initialPageNumber) { +var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); +this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); +} +} +}, +updateListIndices: function() { +if (this.shouldDoRefresh()) { +this.refresh(), this.correctPageHeights(); +return; +} +var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; +if (n === 1) { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); +for (i = t - 1, s = t; i >= e; i--) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); +} +r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); +} else { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); +for (i = e + 1, s = e; i <= t; i++) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); +} +} +}, +shouldDoRefresh: function() { +return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; +}, +getNodeStyle: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) return; +var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); +return { +h: r.height, +w: r.width, +left: n.left, +top: n.top +}; +}, +getRelativeOffset: function(e, t) { +var n = { +top: 0, +left: 0 +}; +if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); +return n; +}, +replaceNodeWithPlaceholder: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) { +enyo.log("No node - " + e); +return; +} +this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); +var n = this.pageForPageNumber(this.currentPageNumber); +n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); +}, +createPlaceholderNode: function(e) { +var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); +return t.style.height = n.height + "px", t.style.width = n.width + "px", t; +}, +removePlaceholderNode: function() { +this.removeNode(this.placeholderNode), this.placeholderNode = null; +}, +removeDraggingRowNode: function() { +this.draggingRowNode = null; +var e = this.$.holdingarea.hasNode(); +e.innerHTML = ""; +}, +removeNode: function(e) { +if (!e || !e.parentNode) return; +e.parentNode.removeChild(e); +}, +updatePageHeight: function(e) { +if (e < 0) return; +var t = this.pageForPageNumber(e, !0); +if (t) { +var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); +this.pageHeights[e] = r, this.portSize += r - n; +} +}, +updatePagePositions: function(e) { +this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); +}, +correctPageHeights: function() { +this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); +}, +hideNode: function(e) { +return e.style.display = "none", e; +}, +showNode: function(e) { +return e.style.display = "block", e; +}, +dropPinnedRow: function(e) { +this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); +return; +}, +cancelPinnedMode: function(e) { +this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); +}, +getRowIndexFromCoordinate: function(e) { +var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; +if (t < 0) return -1; +var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; +if (!r) return this.count; +var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; +for (var u = n.startRow; u <= n.endRow; ++u) { +if (u === this.placeholderRowIndex) { +o += s; +if (o >= i) return -1; +} +if (u !== this.draggingRowIndex) { +o += r[u].height; +if (o >= i) return u; +} +} +return u; +}, +getIndexPosition: function(e) { +return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); +}, +setItemPosition: function(e, t) { +var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; +e.addStyles(i); +}, +setItemBounds: function(e, t) { +var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; +e.addStyles(r); +}, +reorderScroll: function(e, t) { +this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); +}, +hideReorderingRow: function() { +var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); +e && (this.hiddenNode = this.hideNode(e)); +}, +isReordering: function() { +return this.draggingRowIndex > -1; +}, +isSwiping: function() { +return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; +}, +swipeDragStart: function(e, t) { +return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); +}, +swipeDrag: function(e, t) { +return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; +}, +swipeDragFinish: function(e, t) { +if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { +if (!this.isSwiping()) return !1; +var n = this.calcPercentageDragged(this.draggedXDistance); +n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); +} +return this.preventDragPropagation; +}, +isSwipeable: function() { +return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; +}, +positionSwipeableContainer: function(e, t) { +var n = this.$.generator.fetchRowNode(e); +if (!n) return; +var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; +this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); +}, +calcNewDragPosition: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; +return s; +}, +dragSwipeableComponents: function(e) { +this.$.swipeableComponents.applyStyle("left", e + "px"); +}, +startSwipe: function(e) { +e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); +}, +dragPersistentItem: function(e) { +var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); +this.$.swipeableComponents.applyStyle("left", n + "px"); +}, +dragFinishPersistentItem: function(e) { +var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; +this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); +}, +setPersistentItemOrigin: function(e) { +this.persistentItemOrigin = e == 1 ? "left" : "right"; +}, +calcPercentageDragged: function(e) { +return Math.abs(e / this.$.swipeableComponents.getBounds().width); +}, +swipe: function(e) { +this.swipeComplete = !0, this.animateSwipe(0, e); +}, +backOutSwipe: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; +this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; +}, +bounceItem: function(e) { +var t = this.$.swipeableComponents.getBounds(); +t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); +}, +slideAwayItem: function() { +var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; +this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +clearSwipeables: function() { +this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +completeSwipe: function(e) { +this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ +index: this.swipeIndex, +xDirection: this.swipeDirection +})), this.swipeIndex = null, this.swipeDirection = null; +}, +animateSwipe: function(e, t) { +var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; +this.stopAnimateSwipe(); +var u = enyo.bind(this, function() { +var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); +i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { +this.completeSwipe(); +}), this.completeSwipeDelayMS)); +}); +this.job = enyo.requestAnimationFrame(u); +}, +stopAnimateSwipe: function() { +this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); +} +}); + +// PulldownList.js + +enyo.kind({ +name: "enyo.PulldownList", +kind: "List", +touch: !0, +pully: null, +pulldownTools: [ { +name: "pulldown", +classes: "enyo-list-pulldown", +components: [ { +name: "puller", +kind: "Puller" +} ] +} ], +events: { +onPullStart: "", +onPullCancel: "", +onPull: "", +onPullRelease: "", +onPullComplete: "" +}, +handlers: { +onScrollStart: "scrollStartHandler", +onScrollStop: "scrollStopHandler", +ondragfinish: "dragfinish" +}, +pullingMessage: "Pull down to refresh...", +pulledMessage: "Release to refresh...", +loadingMessage: "Loading...", +pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", +pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", +loadingIconClass: "", +create: function() { +var e = { +kind: "Puller", +showing: !1, +text: this.loadingMessage, +iconClass: this.loadingIconClass, +onCreate: "setPully" +}; +this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); +}, +initComponents: function() { +this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); +}, +resetStrategyKind: function() { +return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; +}, +setPully: function(e, t) { +this.pully = t.originator; +}, +scrollStartHandler: function() { +this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; +}, +scroll: function(e, t) { +var n = this.inherited(arguments); +this.completingPull && this.pully.setShowing(!1); +var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); +return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; +}, +scrollStopHandler: function() { +this.completingPull && (this.completingPull = !1, this.doPullComplete()); +}, +dragfinish: function() { +if (this.firedPull) { +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); +} +}, +completePull: function() { +this.completingPull = !0; +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(this.pullHeight), e.start(); +}, +pullStart: function() { +this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); +}, +pull: function() { +this.setPulled(), this.doPull(); +}, +pullCancel: function() { +this.setPulling(), this.doPullCancel(); +}, +pullRelease: function() { +this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); +}, +setPulling: function() { +this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); +}, +setPulled: function() { +this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); +} +}), enyo.kind({ +name: "enyo.Puller", +classes: "enyo-puller", +published: { +text: "", +iconClass: "" +}, +events: { +onCreate: "" +}, +components: [ { +name: "icon" +}, { +name: "text", +tag: "span", +classes: "enyo-puller-text" +} ], +create: function() { +this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); +}, +textChanged: function() { +this.$.text.setContent(this.text); +}, +iconClassChanged: function() { +this.$.icon.setClasses(this.iconClass); +} +}); + +// AroundList.js + +enyo.kind({ +name: "enyo.AroundList", +kind: "enyo.List", +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "aboveClient" +}, { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "belowClient" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0px;" +} ] +} ], +aboveComponents: null, +initComponents: function() { +this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { +owner: this.owner +}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { +owner: this.owner +}); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; +n += r, t.applyStyle(this.pageBound, n + "px"); +}, +scrollToContentStart: function() { +var e = this.bottomUp ? this.belowHeight : this.aboveHeight; +this.setScrollPosition(e); +} +}); + +// Slideable.js + +enyo.kind({ +name: "enyo.Slideable", +kind: "Control", +published: { +axis: "h", +value: 0, +unit: "px", +min: 0, +max: 0, +accelerated: "auto", +overMoving: !0, +draggable: !0 +}, +events: { +onAnimateFinish: "", +onChange: "" +}, +preventDragPropagation: !1, +tools: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorComplete" +} ], +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +kDragScalar: 1, +dragEventProp: "dx", +unitModifier: !1, +canTransform: !1, +create: function() { +this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); +}, +initComponents: function() { +this.createComponents(this.tools), this.inherited(arguments); +}, +rendered: function() { +this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); +}, +resizeHandler: function() { +this.inherited(arguments), this.updateDragScalar(); +}, +canModifyUnit: function() { +if (!this.canTransform) { +var e = this.getInitialStyleValue(this.hasNode(), this.boundary); +e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); +} +}, +getInitialStyleValue: function(e, t) { +var n = enyo.dom.getComputedStyle(e); +return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; +}, +updateBounds: function(e, t) { +var n = {}; +n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); +}, +updateDragScalar: function() { +if (this.unit == "%") { +var e = this.getBounds()[this.dimension]; +this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); +} +}, +transformChanged: function() { +this.canTransform = enyo.dom.canTransform(); +}, +acceleratedChanged: function() { +enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); +}, +axisChanged: function() { +var e = this.axis == "h"; +this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; +}, +setInlineStyles: function(e, t) { +var n = {}; +this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); +}, +valueChanged: function(e) { +var t = this.value; +this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); +}, +getAnimator: function() { +return this.$.animator; +}, +isAtMin: function() { +return this.value <= this.calcMin(); +}, +isAtMax: function() { +return this.value >= this.calcMax(); +}, +calcMin: function() { +return this.min; +}, +calcMax: function() { +return this.max; +}, +clampValue: function(e) { +var t = this.calcMin(), n = this.calcMax(); +return Math.max(t, Math.min(e, n)); +}, +dampValue: function(e) { +return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); +}, +dampBound: function(e, t, n) { +var r = e; +return r * n < t * n && (r = t + (r - t) / 4), r; +}, +percentToPixels: function(e, t) { +return Math.floor(t / 100 * e); +}, +pixelsToPercent: function(e) { +var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; +return e / t * 100; +}, +shouldDrag: function(e) { +return this.draggable && e[this.shouldDragProp]; +}, +isOob: function(e) { +return e > this.calcMax() || e < this.calcMin(); +}, +dragstart: function(e, t) { +if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; +}, +drag: function(e, t) { +if (this.dragging) { +t.preventDefault(); +var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; +return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; +} +}, +dragfinish: function(e, t) { +if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; +}, +completeDrag: function(e) { +this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); +}, +isAnimating: function() { +return this.$.animator.isAnimating(); +}, +play: function(e, t) { +this.$.animator.play({ +startValue: e, +endValue: t, +node: this.hasNode() +}); +}, +animateTo: function(e) { +this.play(this.value, e); +}, +animateToMin: function() { +this.animateTo(this.calcMin()); +}, +animateToMax: function() { +this.animateTo(this.calcMax()); +}, +animateToMinMax: function(e) { +e ? this.animateToMin() : this.animateToMax(); +}, +animatorStep: function(e) { +return this.setValue(e.value), !0; +}, +animatorComplete: function(e) { +return this.doAnimateFinish(e), !0; +}, +toggleMinMax: function() { +this.animateToMinMax(!this.isAtMin()); +} +}); + +// Arranger.js + +enyo.kind({ +name: "enyo.Arranger", +kind: "Layout", +layoutClass: "enyo-arranger", +accelerated: "auto", +dragProp: "ddx", +dragDirectionProp: "xDirection", +canDragProp: "horizontal", +incrementalPoints: !1, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n._arranger = null; +this.inherited(arguments); +}, +arrange: function(e, t) {}, +size: function() {}, +start: function() { +var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; +if (this.incrementalPoints) { +var r = Math.abs(t - e) - 2, i = e; +while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; +} +n.push(this.container.toIndex); +}, +finish: function() {}, +calcArrangementDifference: function(e, t, n, r) {}, +canDragEvent: function(e) { +return e[this.canDragProp]; +}, +calcDragDirection: function(e) { +return e[this.dragDirectionProp]; +}, +calcDrag: function(e) { +return e[this.dragProp]; +}, +drag: function(e, t, n, r, i) { +var s = this.measureArrangementDelta(-e, t, n, r, i); +return s; +}, +measureArrangementDelta: function(e, t, n, r, i) { +var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; +return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; +}, +_arrange: function(e) { +this.containerBounds || this.reflow(); +var t = this.getOrderedControls(e); +this.arrange(t, e); +}, +arrangeControl: function(e, t) { +e._arranger = enyo.mixin(e._arranger || {}, t); +}, +flow: function() { +this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { +enyo.dom.accelerate(n, this.accelerated); +if (enyo.platform.safari) { +var r = n.children; +for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); +} +} +}, +reflow: function() { +var e = this.container.hasNode(); +this.containerBounds = e ? { +width: e.clientWidth, +height: e.clientHeight +} : {}, this.size(); +}, +flowArrangement: function() { +var e = this.container.arrangement; +if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); +}, +flowControl: function(e, t) { +enyo.Arranger.positionControl(e, t); +var n = t.opacity; +n != null && enyo.Arranger.opacifyControl(e, n); +}, +getOrderedControls: function(e) { +var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; +for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); +return this.controlsIndex = t, i; +}, +statics: { +positionControl: function(e, t, n) { +var r = n || "px"; +if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { +var i = t.left, s = t.top; +i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { +translateX: i || null, +translateY: s || null +}); +} else e.setBounds(t, n); +}, +opacifyControl: function(e, t) { +var n = t; +n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); +} +} +}); + +// CardArranger.js + +enyo.kind({ +name: "enyo.CardArranger", +kind: "Arranger", +layoutClass: "enyo-arranger enyo-arranger-fit", +calcArrangementDifference: function(e, t, n, r) { +return this.containerBounds.width; +}, +arrange: function(e, t) { +for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { +opacity: s +}); +}, +start: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); +this.inherited(arguments); +} +}); + +// CardSlideInArranger.js + +enyo.kind({ +name: "enyo.CardSlideInArranger", +kind: "CardArranger", +start: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +var i = this.container.fromIndex; +t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +arrange: function(e, t) { +var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; +for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { +left: l +}); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null +}); +this.inherited(arguments); +} +}); + +// CarouselArranger.js + +enyo.kind({ +name: "enyo.CarouselArranger", +kind: "Arranger", +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; +n.height -= t.top + t.bottom, n.width -= t.left + t.right; +var a; +for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); +if (a) { +var f = n.width - s; +a.width = f >= 0 ? f : a.width; +} +for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ +top: t.top, +bottom: t.bottom, +width: u.fit ? u.width : null +}); +}, +arrange: function(e, t) { +this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); +}, +arrangeNoWrap: function(e, t) { +var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; +for (n = u, i = 0; s = o[n]; n++) { +i += s.width + s.marginWidth; +if (i > a) break; +} +var f = a - i, l = 0; +if (f > 0) { +var c = u; +for (n = u - 1, r = 0; s = o[n]; n--) { +r += s.width + s.marginWidth; +if (f - r <= 0) { +l = f - r, u = n; +break; +} +} +} +var h, p; +for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { +left: -h +}) : (this.arrangeControl(s, { +left: Math.floor(p) +}), p += h); +}, +arrangeWrap: function(e, t) { +for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { +left: r +}), r += s.width + s.marginWidth; +}, +calcArrangementDifference: function(e, t, n, r) { +var i = Math.abs(e % this.c$.length); +return t[i].left - r[i].left; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// CollapsingArranger.js + +enyo.kind({ +name: "enyo.CollapsingArranger", +kind: "CarouselArranger", +peekWidth: 0, +size: function() { +this.clearLastSize(), this.inherited(arguments); +}, +clearLastSize: function() { +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); +}, +constructor: function() { +this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; +}, +arrange: function(e, t) { +var n = this.container.getPanels(); +for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { +left: i + u * this.peekWidth +}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { +left: i +}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { +left: i - t +}); +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels().length - 1; +return Math.abs(r[i].left - t[i].left); +}, +flowControl: function(e, t) { +this.inherited(arguments); +if (this.container.realtimeFit) { +var n = this.container.getPanels(), r = n.length - 1, i = n[r]; +e == i && this.fitControl(e, t.left); +} +}, +finish: function() { +this.inherited(arguments); +if (!this.container.realtimeFit && this.containerBounds) { +var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; +this.fitControl(r, t[n].left); +} +}, +fitControl: function(e, t) { +e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); +} +}); + +// DockRightArranger.js + +enyo.kind({ +name: "enyo.DockRightArranger", +kind: "Arranger", +basePanel: !1, +overlap: 0, +layoutWidth: 0, +constructor: function() { +this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; +n.width -= t.left + t.right; +var o = n.width, u = e.length; +this.container.transitionPositions = {}; +for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; +for (r = 0; s = e[r]; r++) { +r === 0 && this.container.basePanel && s.setBounds({ +width: o +}), s.setBounds({ +top: t.top, +bottom: t.bottom +}); +for (j = 0; s = e[j]; j++) { +var a; +if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { +if (r !== j) break; +var f = o > this.layoutWidth ? this.overlap : 0; +a = o - e[r].width + f; +} +this.container.transitionPositions[r + "." + j] = a; +} +if (j < u) { +var l = !1; +for (k = r + 1; k < u; k++) { +var f = 0; +if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { +f = e[r].width - this.overlap; +for (i = r; i < k; i++) { +var c = f + e[i + 1].width - this.overlap; +if (!(c < o)) { +f = o; +break; +} +f = c; +} +f = o - f; +} +this.container.transitionPositions[r + "." + k] = f; +} +} +} +}, +arrange: function(e, t) { +var n, r, i = this.container.getPanels(), s = this.container.clamp(t); +for (n = 0; r = i[n]; n++) { +var o = this.container.transitionPositions[n + "." + s]; +this.arrangeControl(r, { +left: o +}); +} +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; +return s; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// OtherArrangers.js + +enyo.kind({ +name: "enyo.LeftRightArranger", +kind: "Arranger", +margin: 40, +axisSize: "width", +offAxisSize: "height", +axisPosition: "left", +constructor: function() { +this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; +for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); +}, +start: function() { +this.inherited(arguments); +var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); +for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); +}, +arrange: function(e, t) { +var n, r, i, s; +if (this.container.getPanels().length == 1) { +s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); +return; +} +var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; +for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; +}, +calcArrangementDifference: function(e, t, n, r) { +if (this.container.getPanels().length == 1) return 0; +var i = Math.abs(e % this.c$.length); +return t[i][this.axisPosition] - r[i][this.axisPosition]; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.TopBottomArranger", +kind: "LeftRightArranger", +dragProp: "ddy", +dragDirectionProp: "yDirection", +canDragProp: "vertical", +axisSize: "height", +offAxisSize: "width", +axisPosition: "top" +}), enyo.kind({ +name: "enyo.SpiralArranger", +kind: "Arranger", +incrementalPoints: !0, +inc: 20, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; +for (var i = 0, s; s = e[i]; i++) s.setBounds({ +width: n, +height: r +}); +}, +arrange: function(e, t) { +var n = this.inc; +for (var r = 0, i = e.length, s; s = e[r]; r++) { +var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; +this.arrangeControl(s, { +left: o, +top: u +}); +} +}, +start: function() { +this.inherited(arguments); +var e = this.getOrderedControls(this.container.toIndex); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.controlWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.GridArranger", +kind: "Arranger", +incrementalPoints: !0, +colWidth: 100, +colHeight: 100, +size: function() { +var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; +for (var r = 0, i; i = e[r]; r++) i.setBounds({ +width: t, +height: n +}); +}, +arrange: function(e, t) { +var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; +for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { +left: n * a, +top: r * o +}); +}, +flowControl: function(e, t) { +this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.colWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// Panels.js + +enyo.kind({ +name: "enyo.Panels", +classes: "enyo-panels", +published: { +index: 0, +draggable: !0, +animate: !0, +wrap: !1, +arrangerKind: "CardArranger", +narrowFit: !0 +}, +events: { +onTransitionStart: "", +onTransitionFinish: "" +}, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onscroll: "domScroll" +}, +tools: [ { +kind: "Animator", +onStep: "step", +onEnd: "completed" +} ], +fraction: 0, +create: function() { +this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); +}, +rendered: function() { +this.inherited(arguments), enyo.makeBubble(this, "scroll"); +}, +domScroll: function(e, t) { +this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); +}, +initComponents: function() { +this.createChrome(this.tools), this.inherited(arguments); +}, +arrangerKindChanged: function() { +this.setLayoutKind(this.arrangerKind); +}, +narrowFitChanged: function() { +this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); +}, +destroy: function() { +this.destroying = !0, this.inherited(arguments); +}, +removeControl: function(e) { +this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); +}, +isPanel: function() { +return !0; +}, +flow: function() { +this.arrangements = [], this.inherited(arguments); +}, +reflow: function() { +this.arrangements = [], this.inherited(arguments), this.refresh(); +}, +getPanels: function() { +var e = this.controlParent || this; +return e.children; +}, +getActive: function() { +var e = this.getPanels(), t = this.index % e.length; +return t < 0 && (t += e.length), e[t]; +}, +getAnimator: function() { +return this.$.animator; +}, +setIndex: function(e) { +this.setPropertyValue("index", e, "indexChanged"); +}, +setIndexDirect: function(e) { +this.setIndex(e), this.completed(); +}, +previous: function() { +this.setIndex(this.index - 1); +}, +next: function() { +this.setIndex(this.index + 1); +}, +clamp: function(e) { +var t = this.getPanels().length - 1; +return this.wrap ? e : Math.max(0, Math.min(e, t)); +}, +indexChanged: function(e) { +this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ +startValue: this.fraction +})) : this.refresh())); +}, +step: function(e) { +this.fraction = e.value, this.stepTransition(); +}, +completed: function() { +this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +dragstart: function(e, t) { +if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; +}, +drag: function(e, t) { +this.dragging && (t.preventDefault(), this.dragTransition(t)); +}, +dragfinish: function(e, t) { +this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); +}, +dragstartTransition: function(e) { +if (!this.$.animator.isAnimating()) { +var t = this.fromIndex = this.index; +this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); +} else this.verifyDragTransition(e); +this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); +}, +dragTransition: function(e) { +var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; +a, this.fraction += u; +var f = this.fraction; +if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; +this.stepTransition(); +}, +dragfinishTransition: function(e) { +this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); +}, +verifyDragTransition: function(e) { +var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); +if (t > 0) { +var i = n; +n = r, r = i; +} +n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; +}, +refresh: function() { +this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +startTransition: function() { +this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); +}, +finishTransition: function() { +this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); +}, +fireTransitionStart: function() { +var e = this.startTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { +fromIndex: this.fromIndex, +toIndex: this.toIndex +}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); +}, +fireTransitionFinish: function() { +var e = this.finishTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { +fromIndex: this.lastIndex, +toIndex: this.index +}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; +}, +stepTransition: function() { +if (this.hasNode()) { +var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); +t -= n; +var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); +this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); +} +}, +fetchArrangement: function(e) { +return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; +}, +readArrangement: function(e) { +var t = []; +for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); +return t; +}, +statics: { +isScreenNarrow: function() { +return enyo.dom.getWindowWidth() <= 800; +}, +lerp: function(e, t, n) { +var r = []; +for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); +return r; +}, +lerpObject: function(e, t, n) { +var r = enyo.clone(e), i, s; +if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); +return r; +} +} +}); + +// Node.js + +enyo.kind({ +name: "enyo.Node", +published: { +expandable: !1, +expanded: !1, +icon: "", +onlyIconExpands: !1, +selected: !1 +}, +style: "padding: 0 0 0 16px;", +content: "Node", +defaultKind: "Node", +classes: "enyo-node", +components: [ { +name: "icon", +kind: "Image", +showing: !1 +}, { +kind: "Control", +name: "caption", +Xtag: "span", +style: "display: inline-block; padding: 4px;", +allowHtml: !0 +}, { +kind: "Control", +name: "extra", +tag: "span", +allowHtml: !0 +} ], +childClient: [ { +kind: "Control", +name: "box", +classes: "enyo-node-box", +Xstyle: "border: 1px solid orange;", +components: [ { +kind: "Control", +name: "client", +classes: "enyo-node-client", +Xstyle: "border: 1px solid lightblue;" +} ] +} ], +handlers: { +ondblclick: "dblclick" +}, +events: { +onNodeTap: "nodeTap", +onNodeDblClick: "nodeDblClick", +onExpand: "nodeExpand", +onDestroyed: "nodeDestroyed" +}, +create: function() { +this.inherited(arguments), this.selectedChanged(), this.iconChanged(); +}, +destroy: function() { +this.doDestroyed(), this.inherited(arguments); +}, +initComponents: function() { +this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); +}, +contentChanged: function() { +this.$.caption.setContent(this.content); +}, +iconChanged: function() { +this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); +}, +selectedChanged: function() { +this.addRemoveClass("enyo-selected", this.selected); +}, +rendered: function() { +this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); +}, +addNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent(n); +this.$.client.render(); +}, +addTextNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent({ +content: n +}); +this.$.client.render(); +}, +tap: function(e, t) { +return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; +}, +dblclick: function(e, t) { +return this.doNodeDblClick(), !0; +}, +toggleExpanded: function() { +this.setExpanded(!this.expanded); +}, +quickCollapse: function() { +this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); +var e = this.$.client.getBounds().height; +this.$.client.setBounds({ +top: -e +}); +}, +_expand: function() { +this.addClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), this.$.client.setBounds({ +top: 0 +}), setTimeout(enyo.bind(this, function() { +this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); +}), 225); +}, +_collapse: function() { +this.removeClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), setTimeout(enyo.bind(this, function() { +this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ +top: -e +}); +}), 25); +}, +expandedChanged: function(e) { +if (!this.expandable) this.expanded = !1; else { +var t = { +expanded: this.expanded +}; +this.doExpand(t), t.wait || this.effectExpanded(); +} +}, +effectExpanded: function() { +this.$.client && (this.expanded ? this._expand() : this._collapse()); +} +}); + +// ImageViewPin.js + +enyo.kind({ +name: "enyo.ImageViewPin", +kind: "enyo.Control", +published: { +highlightAnchorPoint: !1, +anchor: { +top: 0, +left: 0 +}, +position: { +top: 0, +left: 0 +} +}, +style: "position:absolute;z-index:1000;width:0px;height:0px;", +handlers: { +onPositionPin: "reAnchor" +}, +create: function() { +this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); +}, +styleClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); +}, +positionClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); +}, +highlightAnchorPointChanged: function() { +this.addRemoveClass("pinDebug", this.highlightAnchorPoint); +}, +anchorChanged: function() { +var e = null, t = null; +for (t in this.anchor) { +e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); +if (!e) continue; +this.anchor[t + "Coords"] = { +value: e[1], +units: e[2] || "px" +}; +} +}, +reAnchor: function(e, t) { +var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; +this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); +} +}); + +// ImageView.js + +enyo.kind({ +name: "enyo.ImageView", +kind: enyo.Scroller, +touchOverscroll: !1, +thumb: !1, +animate: !0, +verticalDragPropagation: !0, +horizontalDragPropagation: !0, +published: { +scale: "auto", +disableZoom: !1, +src: undefined +}, +events: { +onZoom: "" +}, +touch: !0, +preventDragPropagation: !1, +handlers: { +ondragstart: "dragPropagation" +}, +components: [ { +name: "animator", +kind: "Animator", +onStep: "zoomAnimationStep", +onEnd: "zoomAnimationEnd" +}, { +name: "viewport", +style: "overflow:hidden;min-height:100%;min-width:100%;", +classes: "enyo-fit", +ongesturechange: "gestureTransform", +ongestureend: "saveState", +ontap: "singleTap", +ondblclick: "doubleClick", +onmousewheel: "mousewheel", +components: [ { +kind: "Image", +ondown: "down" +} ] +} ], +create: function() { +this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); +}, +down: function(e, t) { +t.preventDefault(); +}, +dragPropagation: function(e, t) { +var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; +return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); +}, +mousewheel: function(e, t) { +t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; +var n = (this.maxScale - this.minScale) / 10, r = this.scale; +if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); +return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; +}, +srcChanged: function() { +this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); +}, +imageLoaded: function(e) { +this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); +}, +resizeHandler: function() { +this.inherited(arguments), this.$.image.src && this.scaleChanged(); +}, +scaleChanged: function() { +var e = this.hasNode(); +if (e) { +this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; +var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; +this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); +} +this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); +}, +imageError: function(e) { +enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); +}, +alignImage: function() { +if (this.fitAlignment && this.fitAlignment === "center") { +var e = this.getScrollBounds(); +this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); +} +}, +gestureTransform: function(e, t) { +this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); +}, +calcEventLocation: function(e) { +var t = { +x: 0, +y: 0 +}; +if (e && this.hasNode()) { +var n = this.node.getBoundingClientRect(); +t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); +} +return t; +}, +transformImage: function(e) { +this.tapped = !1; +var t = this.imageBounds || this.innerImageBounds(e); +this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px" +}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; +var n, r; +this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); +if (this.canTransform) { +var i = { +scale: e +}; +this.canAccelerate ? i = enyo.mixin({ +translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" +}, i) : i = enyo.mixin({ +translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" +}, i), enyo.dom.transform(this.$.image, i); +} else this.$.image.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px", +left: this.imageBounds.left + "px", +top: this.imageBounds.top + "px" +}); +this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); +}, +limitScale: function(e) { +return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; +}, +innerImageBounds: function(e) { +var t = this.originalWidth * e, n = this.originalHeight * e, r = { +x: 0, +y: 0, +transX: 0, +transY: 0 +}; +return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { +left: r.x + r.transX, +top: r.y + r.transY, +width: t, +height: n, +x: r.x, +y: r.y +}; +}, +saveState: function(e, t) { +var n = this.scale; +this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null; +}, +doubleClick: function(e, t) { +enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); +}, +singleTap: function(e, t) { +setTimeout(enyo.bind(this, function() { +this.tapped = !1; +}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; +}, +smartZoom: function(e, t) { +var n = this.hasNode(), r = this.$.image.hasNode(); +if (n && r && this.hasNode() && !this.disableZoom) { +var i = this.scale; +this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); +if (this.animate) { +var s = { +x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, +y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height +}; +this.$.animator.play({ +duration: 350, +ratioLock: s, +baseScale: i, +deltaScale: this.scale - i +}); +} else this.transformImage(this.scale), this.doZoom({ +scale: this.scale +}); +} +}, +zoomAnimationStep: function(e, t) { +var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; +this.transformImage(n); +}, +zoomAnimationEnd: function(e, t) { +this.doZoom({ +scale: this.scale +}), this.$.animator.ratioLock = undefined; +}, +positionClientControls: function(e) { +this.waterfallDown("onPositionPin", { +scale: e, +bounds: this.imageBounds +}); +} +}); + +// ImageCarousel.js + +enyo.kind({ +name: "enyo.ImageCarousel", +kind: enyo.Panels, +arrangerKind: "enyo.CarouselArranger", +defaultScale: "auto", +disableZoom: !1, +lowMemory: !1, +published: { +images: [] +}, +handlers: { +onTransitionStart: "transitionStart", +onTransitionFinish: "transitionFinish" +}, +create: function() { +this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); +}, +initContainers: function() { +for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ +name: "container" + e, +style: "height:100%; width:100%;" +}), this.$["container" + e].render()); +for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); +this.imageCount = this.images.length; +}, +loadNearby: function() { +var e = this.getBufferRange(); +for (var t in e) this.loadImageView(e[t]); +}, +getBufferRange: function() { +var e = []; +if (this.layout.containerBounds) { +var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; +o = this.index - 1, u = 0, a = n.width * t; +while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; +o = this.index, u = 0, a = n.width * (t + 1); +while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; +} +return e; +}, +reflow: function() { +this.inherited(arguments), this.loadNearby(); +}, +loadImageView: function(e) { +return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ +name: "image" + e, +kind: "ImageView", +scale: this.defaultScale, +disableZoom: this.disableZoom, +src: this.images[e], +verticalDragPropagation: !1, +style: "height:100%; width:100%;" +}, { +owner: this +}), this.$["image" + e].render())), this.$["image" + e]; +}, +setImages: function(e) { +this.setPropertyValue("images", e, "imagesChanged"); +}, +imagesChanged: function() { +this.initContainers(), this.loadNearby(); +}, +indexChanged: function() { +this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); +}, +transitionStart: function(e, t) { +if (t.fromIndex == t.toIndex) return !0; +}, +transitionFinish: function(e, t) { +this.loadNearby(), this.lowMemory && this.cleanupMemory(); +}, +getActiveImage: function() { +return this.getImageByIndex(this.index); +}, +getImageByIndex: function(e) { +return this.$["image" + e] || this.loadImageView(e); +}, +cleanupMemory: function() { +var e = getBufferRange(); +for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); +} +}); + +// runtime-machine.js + +runtimeMachine = { +_head: function(e, t, n) { +this._inflight = !0; +var r = document.createElement(e); +for (var i in t) r.setAttribute(i, t[i]); +return n && (r.innerText = n), this._headElt || (this._headElt = document.getElementsByTagName("head")[0]), this._headElt.appendChild(r), r; +}, +sheet: function(e) { +this._head("link", { +type: "text/css", +media: "screen", +rel: "stylesheet", +href: e +}); +}, +inject: function(e) { +this._head("script", { +type: "text/javascript" +}, e); +}, +_scripts: [], +script: function(e) { +this._inflight ? this._scripts.push(e) : this._script(e); +}, +_require: function(e) {}, +_script: function(e) { +this._inflight = !0; +var t = this._head("script", { +type: "text/javascript", +src: e +}), n = this; +enyo.platform.ie && enyo.platform.ie <= 8 ? t.onreadystatechange = function() { +if (t.readyState === "complete" || t.readyState === "loaded") t.onreadystatechange = "", n._loaded(e); +} : (t.onload = function() { +n._loaded(e); +}, t.onerror = function() { +n._error(e); +}); +}, +_continue: function() { +this._inflight = !1; +var e = this._scripts.pop(); +e && this._script(e); +}, +_loaded: function(e) { +this._continue(); +}, +_error: function(e) { +this._continue(); +} +}; + +// AnalyzerDebug.js + +enyo.kind({ +name: "AnalyzerDebug", +kind: null, +debug: !1, +_level: 0, +methodName: function(e) { +var t = this.getStackInfo(3 + (e || 0)); +return t = t.replace(/ .http:.*$/g, ""), t = t.replace(/^.*.enyo.kind/g, this.kindName), t += " ", t.substr(0, 30); +}, +getCurrentStackInfo: function(e) { +return " current: " + this.getStackInfo(3 + (e || 0)); +}, +getPreviousStackInfo: function(e) { +return " previous: " + this.getStackInfo(4 + (e || 0)); +}, +getStackInfo: function(e) { +try { +throw new Error; +} catch (t) { +var n = t.stack; +if (n) { +var r = n.split("\n"); +return r[e]; +} +return "(stack trace not available)"; +} +}, +showLevel: function() { +return "#####################################".substr(0, this._level) + " "; +}, +incremLevel: function() { +return this._level++, this.showLevel() + " --> "; +}, +decremLevel: function() { +var e = this.showLevel() + " <-- "; +return this._level--, e; +}, +showIterator: function(e) { +return e ? "[" + e.ID + "/" + e.i + "] " : ""; +}, +logMethodEntry: function(e, t) { +t = t || "", enyo.log(this.methodName(1) + this.incremLevel() + this.showIterator(e) + t + this.getPreviousStackInfo(1)); +}, +logMethodExit: function(e, t) { +t = t || "", enyo.log(this.methodName(1) + this.decremLevel() + this.showIterator(e) + t + this.getCurrentStackInfo(1)); +}, +logProcessing: function(e, t) { +enyo.log(this.methodName(1) + this.showLevel() + this.showIterator(e) + "PROCESSING kind: " + t.kind + " >>" + t.token + "<< line: " + t.line + this.getCurrentStackInfo(1)); +}, +logIterMsg: function(e, t) { +enyo.log(this.methodName(1) + this.showLevel() + this.showIterator(e) + t + this.getPreviousStackInfo(1)); +}, +logMsg: function(e) { +enyo.log(this.methodName(1) + this.showLevel() + e + this.getPreviousStackInfo(1)); +}, +statics: { +_debugEnabled: !1 +} +}); + +// Walker.js + +enyo.kind({ +name: "Walker", +kind: enyo.Component, +published: { +verbose: !1 +}, +events: { +onProgress: "", +onFinish: "" +}, +walk: function(e, t) { +return this.verbose && this.log("inPath: " + e + " resolver: ", t), this.loader = new enyo.loaderFactory(runtimeMachine, t), this.loader.loadScript = function() {}, this.loader.loadSheet = function() {}, this.loader.verbose = this.verbose, this.loader.report = enyo.bind(this, "walkReport"), this.loader.finish = enyo.bind(this, "walkFinish"), enyo.loader = this.loader, t ? (path = t.rewrite(e), this.verbose && path !== e && this.log("inPathResolver: " + e + " ==> " + path)) : (path = enyo.path.rewrite(e), this.verbose && path !== e && this.log("enyo.path: " + e + " ==> " + path)), enyo.asyncMethod(this.loader, "load", path), this.async = new enyo.Async; +}, +walkReport: function(e, t) { +this.doProgress({ +action: e, +name: t +}); +}, +walkFinish: function() { +this.modules = this.loader.modules, this.async.respond({ +modules: this.modules +}), this.doFinish({ +modules: this.modules +}); +} +}); + +// Reader.js + +enyo.kind({ +name: "Reader", +kind: enyo.Async, +go: function(e) { +return this.modules = e.modules, this.moduleIndex = 0, enyo.asyncMethod(this, "nextModule"), this; +}, +nextModule: function() { +var e = this.modules[this.moduleIndex++]; +e ? this.loadModule(e) : this.modulesFinished(); +}, +loadModule: function(e) { +enyo.xhr.request({ +url: e.path, +callback: enyo.bind(this, "moduleLoaded", e) +}); +}, +moduleLoaded: function(e, t) { +this.addModule(e, t), this.nextModule(); +}, +addModule: function(e, t) { +t && t.length && (e.code = t); +}, +modulesFinished: function() { +this.respond({ +modules: this.modules +}); +} +}); + +// Iterator.js + +enyo.kind({ +name: "Iterator", +kind: null, +i: -1, +nodes: null, +constructor: function(e) { +this.ID = Iterator._objectCount++, this.stream = e; +}, +statics: { +_objectCount: 0 +}, +next: function() { +return this.i++, this._read(); +}, +prev: function() { +return this.i--, this._read(); +}, +_read: function(e) { +return this.past = this.stream[this.i - 1], this.value = this.stream[this.i], this.future = this.stream[this.i + 1], this.value; +} +}); + +// Lexer.js + +enyo.kind({ +name: "AbstractLexer", +kind: null, +constructor: function(e) { +if (e) return this.start(e), this.finish(), this.r; +}, +p0: 0, +p: 0, +start: function(e) { +this.s = e, this.l = this.s.length, this.r = [], this.d = "", this.p0 = 0, this.p = 0, this.n = 0, this.analyze(); +}, +search: function(e) { +var t = e.global ? e : new RegExp(e.source, "g"); +return t.lastIndex = this.p, this.m = t.exec(this.s), this.p = this.m ? this.m.index : -1, t.lastIndex != this.p0 && (this.d = this.s.charAt(this.p)); +}, +lookahead: function(e) { +return this.s.charAt(this.p + e); +}, +getToken: function() { +return this.s.slice(this.p0, this.p); +}, +tokenize: function(e) { +this.p += e || 0; +}, +pushToken: function(e, t, n) { +this.tokenize(t); +var r = this.getToken(); +if (!r && !n) return {}; +var i = (r.match(/\n/g) || []).length, s = { +kind: e, +token: r, +start: this.p0, +end: this.p, +line: this.n, +height: i +}; +return this.r.push(s), this.n += i, this.p0 = this.p, s; +}, +tossToken: function(e) { +this.tokenize(e), this.p0 = this.p; +}, +finish: function() { +this.pushToken("gah"); +} +}), enyo.kind({ +name: "Lexer", +kind: AbstractLexer, +symbols: "(){}[];,:<>+-=*/&", +operators: [ "++", "--", "+=", "-=", "==", "!=", "<=", ">=", "===", "&&", "||", '"', "'" ], +keywords: [ "function", "new", "return", "if", "else", "while", "do", "break", "continue", "switch", "case", "var" ], +constructor: function(e) { +return this.buildPattern(), this.inherited(arguments); +}, +buildPattern: function() { +var e = '"(?:\\\\"|[^"])*?"', t = "'(?:\\\\'|[^'])*?'", n = e + "|" + t, r = "\\b(?:" + this.keywords.join("|") + ")\\b", i = "[\\" + this.symbols.split("").join("\\") + "]", s = []; +for (var o = 0, u; u = this.operators[o]; o++) s.push("\\" + u.split("").join("\\")); +s = s.join("|"), i = s + "|" + i; +var a = [ '\\\\"|\\\\/', n, r, "\\/\\/", "\\/\\*", i, "\\s" ]; +this.matchers = [ "doSymbol", "doString", "doKeyword", "doLineComment", "doCComment", "doSymbol", "doWhitespace" ], this.pattern = "(" + a.join(")|(") + ")"; +}, +analyze: function() { +var e = new RegExp(this.pattern, "gi"); +while (this.search(e)) this.pushToken("identifier"), this.process(this.matchers), this.pushToken("identifier"); +}, +process: function(e) { +for (var t = 0, n; n = e[t]; t++) if (this.m[t + 1] && this[n]) { +this[n].apply(this); +return; +} +this.doSymbol(); +}, +doWhitespace: function() { +this.tokenize(1), this.search(/\S/g), this.pushToken("ws"), this.r.pop(); +}, +doEscape: function() { +this.tokenize(2); +}, +doLiteral: function() { +this.tossToken(1); +var e = this.d, t = new RegExp("\\" + e + "|\\\\", "g"); +while (this.search(t)) switch (this.d) { +case "\\": +this.doEscape(); +break; +default: +this.pushToken("literal", 0, !0).delimiter = e, this.tossToken(1); +return; +} +}, +doSymbol: function() { +this.pushToken(this.d == ";" || this.d == "," ? "terminal" : "symbol", this.m[0].length); +}, +doKeyword: function() { +this.pushToken("keyword", this.m[0].length); +}, +doLineComment: function() { +this.tokenize(2), this.search(/[\r\n]/g) && this.tokenize(0), this.pushToken("comment"); +}, +doCComment: function() { +this.tokenize(2); +var e = 1; +while (e && this.search(/\/\*|\*\//g)) e += this.d == "/" ? 1 : this.d == "*" ? -1 : 0, this.tokenize(2); +this.pushToken("comment"); +}, +doString: function() { +this.pushToken("string", this.m[0].length); +} +}); + +// Parser.js + +enyo.kind({ +name: "Parser", +kind: "AnalyzerDebug", +constructor: function(e) { +return this.debug = AnalyzerDebug._debugEnabled, this.parse(e); +}, +parse: function(e) { +var t = [], n = new Iterator(e); +while (n.next()) n.value.kind !== "ws" && t.push(n.value); +var n = new Iterator(t); +return this.walk(n); +}, +combine: function(e) { +var t = ""; +for (var n = 0, r; r = e[n]; n++) t += r.token; +return t; +}, +walk: function(e, t) { +this.debug && this.logMethodEntry(e, "inState " + t + " >>" + JSON.stringify(e.value) + "<<"); +var n = [], r; +try { +while (e.next()) { +r = e.value, this.debug && this.logProcessing(e, r); +if (r.kind == "ws") continue; +if (r.kind == "comment") r.kind = "comment"; else if (t == "array") { +if (r.kind == "terminal") continue; +e.prev(); +var i = e.value; +r = { +kind: "element", +token: "expr", +children: this.walk(e, "expression") +}; +if (e.value && e.value.token == "]" || e.value && e.value === i) return r.children.length && n.push(r), this.debug && this.logMethodExit(e), n; +} else if (r.token == "[") r.kind = "array", r.children = this.walk(e, r.kind), e.value ? r.end = e.value.end : this.debug && this.logIterMsg(e, "No end token for array?"); else { +if (t == "expression" && r.token == "]") return this.debug && this.logMethodExit(e), n; +if (r.token == "var") r.kind = "var", r.children = this.walk(e, "expression"); else { +if (r.kind == "terminal" && (t == "expression" || t == "var")) return this.debug && this.logMethodExit(e), n; +if (r.kind == "terminal") continue; +if (r.token == "{") { +r.kind = "block", this.debug && this.logIterMsg(e, "PROCESS BLOCK - START"), r.children = this.walk(e, r.kind), this.debug && this.logIterMsg(e, "PROCESS BLOCK - END"), e.value ? r.end = e.value.end : this.debug && this.logIterMsg(e, "No end token for block?"), r.commaTerminated = this.isCommaTerminated(e); +if (t == "expression" || t == "function") return n.push(r), this.debug && this.logMethodExit(e), n; +} else { +if (t == "expression" && (r.token == "}" || r.token == ")")) return e.prev(), this.debug && this.logMethodExit(e), n; +if (t == "block" && r.token == "}") return this.debug && this.logMethodExit(e), n; +if (r.token == "=" || r.token == ":" && t != "expression") { +var s = n.pop(); +s.kind == "identifier" ? (s.op = r.token, s.kind = "assignment", s.children = this.walk(e, "expression"), e.value && e.value.kind == "terminal" && (s.commaTerminated = e.value.token === ",", e.prev()), r = s) : n.push(s); +} else if (r.token == "(") r.kind = "association", r.children = this.walk(e, r.kind); else { +if (t == "association" && r.token == ")") return this.debug && this.logMethodExit(e), n; +if (r.token == "function") { +r.kind = "function", this.debug && this.logIterMsg(e, "PROCESS FUNCTION - START"), r.children = this.walk(e, r.kind), this.debug && this.logIterMsg(e, "PROCESS FUNCTION - END"), (!e.value || e.value.kind !== "symbol" || e.value.token !== "}") && this.debug && this.logIterMsg(e, "No end token for function?"); +if (t !== "expression" && r.children && r.children.length && r.children[0].kind == "identifier") { +this.debug && this.logIterMsg(e, "C-Style function"), r.name = r.children[0].token, r.children.shift(); +var o = { +kind: "assignment", +token: r.name, +children: [ r ] +}; +r = o; +} +if (t == "expression" || t == "function") return r.commaTerminated = this.isCommaTerminated(e), n.push(r), this.debug && this.logMethodExit(e), n; +} +} +} +} +} +this.debug && this.logIterMsg(e, "PUSH NODE"), n.push(r); +} +} catch (u) { +console.error(u); +} +return this.debug && this.logMethodExit(e), n; +}, +isCommaTerminated: function(e) { +commaPresent = !1; +var t = e.next(); +return t && (commaPresent = t.kind === "terminal" && t.token === ","), e.prev(), commaPresent; +} +}); + +// Documentor.js + +enyo.kind({ +name: "Documentor", +kind: "AnalyzerDebug", +group: "public", +constructor: function(e) { +return this.comment = [], this.debug = AnalyzerDebug._debugEnabled, this.parse(e); +}, +parse: function(e) { +var t = new Iterator(e); +return this.walk(t); +}, +walk: function(e, t) { +var n = [], r, i; +this.debug && this.logMethodEntry(e, "inState " + t + " >>" + JSON.stringify(e.value) + "<<"); +while (e.next()) { +r = e.value, this.debug && this.logProcessing(e, r); +if (r.kind == "comment") this.cook_comment(r.token); else if (r.token == "enyo.kind" && e.future.kind == "association") i = this.cook_kind(e); else if (r.kind == "assignment") i = this.cook_assignment(e); else if (r.kind == "association" && r.children && r.children.length == 1 && r.children[0].kind == "function") { +var s = r.children[0]; +if (s.children && s.children.length == 2) { +var o = s.children[1], u = this.walk(new Iterator(o.children)); +n = n.concat(u); +} +e.next(); +} +i && (n.push(i), i = null); +} +return this.debug && this.logMethodExit(e), n; +}, +cook_kind: function(e) { +this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); +var t = function(e, t) { +var n = Documentor.indexByName(e, t), r; +return n >= 0 && (r = e[n], e.splice(r, 1)), r && r.value && r.value.length && r.value[0].token; +}, n = this.make("kind", e.value); +e.next(); +var r = e.value.children; +return r && r[0] && r[0].kind == "block" && (n.properties = this.cook_block(r[0].children), n.name = Documentor.stripQuotes(t(n.properties, "name") || ""), n.superkind = Documentor.stripQuotes(t(n.properties, "kind") || "enyo.Control"), n.superkind == "null" && (n.superkind = null), n.block = { +start: r[0].start, +end: r[0].end +}), this.debug && this.logMethodExit(e), n; +}, +cook_block: function(e) { +this.debug && this.logMethodEntry(); +var t = []; +for (var n = 0, r; r = e[n]; n++) { +this.debug && this.logProcessing(null, r); +if (r.kind == "comment") this.cook_comment(r.token); else if (r.kind == "assignment") { +var i = this.make("property", r); +r.children && (i.value = [ this.walkValue(new Iterator(r.children)) ], r.commaTerminated === undefined ? (i.commaTerminated = r.children[0].commaTerminated || !1, r.children[0].commaTerminated === undefined && this.debug && this.logMsg("NO COMMA TERMINATED INFO")) : i.commaTerminated = r.commaTerminated), t.push(i); +} +} +return this.debug && this.logMethodExit(), t; +}, +walkValue: function(e, t) { +this.debug && this.logMethodEntry(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"); +while (e.next()) { +var n = e.value, r; +this.debug && this.logProcessing(e, n); +if (n.kind != "comment") { +if (n.kind == "block") return r = this.make("block", n), r.properties = this.cook_block(n.children), this.debug && this.logMethodExit(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"), r; +if (n.kind == "array") return r = this.cook_array(e), this.debug && this.logMethodExit(e), r; +if (n.kind == "function") return r = this.cook_function(e), this.debug && this.logMethodExit(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"), r; +r = this.make("expression", n); +var i = n.token; +while (e.next()) i += e.value.token; +return r.token = i, this.debug && this.logMethodExit(e), r; +} +this.cook_comment(n.token); +} +this.debug && this.logMethodExit(e); +}, +cook_function: function(e) { +this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); +var t = e.value, n = this.make("expression", t); +return n.commaTerminated = t.commaTerminated, n.arguments = enyo.map(t.children[0].children, function(e) { +return e.token; +}), this.debug && this.logMethodExit(e), n; +}, +cook_array: function(e) { +this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); +var t = e.value, n = this.make("array", t), r = t.children; +if (r) { +var i = []; +for (var s = 0, o, u; o = r[s]; s++) o.children && (u = this.walkValue(new Iterator(o.children)), u && i.push(u)); +n.properties = i; +} +return this.debug && this.logMethodExit(e), n; +}, +cook_assignment: function(e) { +this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); +var t = e.value, n = this.make("global", t); +return t.children && (t.children[0] && t.children[0].token == "function" && (n.type = "function"), n.value = [ this.walkValue(new Iterator(t.children)) ]), this.debug && this.logMethodExit(), n; +}, +make: function(e, t) { +return { +line: t.line, +start: t.start, +end: t.end, +height: t.height, +token: t.token, +name: t.token, +type: e, +group: this.group, +comment: this.consumeComment() +}; +}, +commentRx: /\/\*\*([\s\S]*)\*\/|\/\/\*(.*)/m, +cook_comment: function(e) { +this.debug && this.logMethodEntry(); +var t = e.match(this.commentRx); +if (t) { +t = t[1] ? t[1] : t[2]; +var n = this.extractPragmas(t); +this.honorPragmas(n); +} +this.debug && this.logMethodExit(); +}, +extractPragmas: function(e) { +var t = /^[*\s]*@[\S\s]*/g, n = [], r = e; +return r.length && (r = e.replace(t, function(e) { +var t = e.slice(2); +return n.push(t), ""; +}), r.length && this.comment.push(r)), n; +}, +honorPragmas: function(e) { +var t = { +"protected": 1, +"public": 1 +}; +for (var n = 0, r; r = e[n]; n++) t[r] && (this.group = r); +}, +consumeComment: function() { +var e = this.comment.join(" "); +this.comment = []; +var t = Documentor.removeIndent(e); +return t; +}, +statics: { +indexByProperty: function(e, t, n) { +for (var r = 0, i; i = e[r]; r++) if (i[t] == n) return r; +return -1; +}, +findByProperty: function(e, t, n) { +return e[this.indexByProperty(e, t, n)]; +}, +indexByName: function(e, t) { +return this.indexByProperty(e, "name", t); +}, +findByName: function(e, t) { +return e[this.indexByName(e, t)]; +}, +stripQuotes: function(e) { +var t = e.charAt(0), n = t == '"' || t == "'" ? 1 : 0, r = e.charAt(e.length - 1), i = r == '"' || r == "'" ? -1 : 0; +return n || i ? e.slice(n, i) : e; +}, +removeIndent: function(e) { +var t = 0, n = e.split(/\r?\n/), r, i; +for (r = 0; (i = n[r]) != null; r++) if (i.length > 0) { +t = i.search(/\S/), t < 0 && (t = i.length); +break; +} +if (t) for (r = 0; (i = n[r]) != null; r++) n[r] = i.slice(t); +return n.join("\n"); +} +} +}); + +// Indexer.js + +enyo.kind({ +name: "Indexer", +kind: null, +group: "public", +constructor: function() { +this.objects = []; +}, +debug: !1, +findByName: function(e) { +return Documentor.findByProperty(this.objects, "name", e); +}, +findByTopic: function(e) { +return Documentor.findByProperty(this.objects, "topic", e); +}, +search: function(e, t, n) { +var r = enyo.filter(this.objects, e, n); +return enyo.map(r, t, n); +}, +addModules: function(e) { +enyo.forEach(e, this.addModule, this), this.objects.sort(Indexer.nameCompare); +}, +addModule: function(e) { +this.debug && enyo.log("Indexer.addModule(): + " + e.path), this.indexModule(e), this.mergeModule(e); +}, +mergeModule: function(e) { +this.objects.push(e), this.objects = this.objects.concat(e.objects), enyo.forEach(e.objects, this.mergeProperties, this); +}, +mergeProperties: function(e) { +e.properties ? this.objects = this.objects.concat(e.properties) : e.value && e.value[0] && e.value[0].properties && (this.objects = this.objects.concat(e.value[0].properties)); +}, +indexModule: function(e) { +e.type = "module", e.name = e.path ? e.path.replace("lib/", "") : e.label + "/" + e.rawPath, e.objects = new Documentor(new Parser(new Lexer(e.code))), this.indexObjects(e); +}, +indexObjects: function(e) { +enyo.forEach(e.objects, function(t) { +t.module = e, this.indexObject(t); +}, this); +}, +indexObject: function(e) { +switch (e.type) { +case "kind": +this.indexKind(e); +} +this.indexProperties(e); +}, +indexProperties: function(e) { +var t = e.properties || e.value && e.value[0] && e.value[0].properties; +enyo.forEach(t, function(t) { +t.object = e, t.topic = t.object.name ? t.object.name + "::" + t.name : t.name; +}, this); +}, +indexKind: function(e) { +this.listComponents(e), this.indexInheritance(e); +}, +indexInheritance: function(e) { +e.superkinds = this.listSuperkinds(e), e.allProperties = this.listInheritedProperties(e); +}, +listSuperkinds: function(e) { +var t = [], n; +while (e && e.superkind) n = e.superkind, e = this.findByName(n), e || (e = this.findByName("enyo." + n), e && (n = "enyo." + n)), t.push(n); +return t; +}, +listInheritedProperties: function(e) { +var t = [], n = {}; +for (var r = e.superkinds.length - 1, i; i = e.superkinds[r]; r--) { +var s = this.findByName(i); +s && this.mergeInheritedProperties(s.properties, n, t); +} +return this.mergeInheritedProperties(e.properties, n, t), t.sort(Indexer.nameCompare), t; +}, +mergeInheritedProperties: function(e, t, n) { +for (var r = 0, i; i = e[r]; r++) { +var s = t.hasOwnProperty(i.name) && t[i.name]; +s ? (i.overrides = s, n[enyo.indexOf(s, n)] = i) : n.push(i), t[i.name] = i; +} +}, +listComponents: function(e) { +e.components = this._listComponents(e, [], {}); +var t = Documentor.findByName(e.properties, "components"); +t && t.value && (e.componentsBlockStart = t.value[0].start, e.componentsBlockEnd = t.value[0].end); +}, +_listComponents: function(e, t, n) { +var r = Documentor.findByName(e.properties, "components"); +if (r && r.value && r.value.length) { +var i = r.value[0].properties; +for (var s = 0, o; o = i[s]; s++) { +var u = Documentor.findByName(o.properties, "name"); +u && (u = Documentor.stripQuotes(u.value[0].token || "")); +var a = Documentor.findByName(o.properties, "kind"); +a = Documentor.stripQuotes(a && a.value[0].token || "Control"); +if (!u) { +var f = a.split(".").pop(); +u = enyo.uncap(f), n[u] ? u += ++n[u] : n[u] = 1; +} +o.kind = a, o.name = u, t.push(o), this._listComponents(o, t, n); +} +} +return t; +}, +statics: { +nameCompare: function(e, t) { +var n = e.name.toLowerCase(), r = t.name.toLowerCase(); +return n < r ? -1 : n > r ? 1 : 0; +} +} +}); + +// Analyzer.js + +enyo.kind({ +name: "Analyzer", +kind: "Component", +debug: !1, +events: { +onIndexReady: "" +}, +create: function() { +this.index = new Indexer, this.inherited(arguments); +}, +analyze: function(e, t) { +this.walk(e, t); +}, +walk: function(e, t) { +var n = [], r, i = function(s, o) { +if (o) { +this.debug && enyo.log("Analyzer.walk.next() - inData: ", o); +for (var u = 0; u < o.modules.length; ++u) o.modules[u].label = r; +n = n.concat(o.modules); +} +var a = e.shift(), f = ""; +a ? (this.debug && enyo.log("Analyzer.walk.next() - path: " + a), enyo.isString(a) || (r = a.label, a = a.path), (new Walker).walk(a, t).response(this, i)) : this.walkFinished(n); +}; +i.call(this); +}, +walkFinished: function(e) { +this.read(e); +}, +read: function(e) { +(new Reader).go({ +modules: e +}).response(this, function(e, t) { +this.indexModules(t.modules); +}); +}, +indexModules: function(e) { +this.index.addModules(e), this.doIndexReady(); +} +}); + +// KindHelper.js + +enyo.kind({ +name: "Analyzer.KindHelper", +kind: "enyo.Component", +published: { +definition: null +}, +checkDefAvail: function() { +if (!this.definition) throw "No definition provided"; +}, +getEvents: function() { +this.checkDefAvail(); +var e = []; +obj = this.definition.properties; +for (i = 0; i < obj.length; i++) if (obj[i].token === "events") { +p = obj[i].value[0].properties; +for (var t = 0; t < p.length; t++) { +var n = p[t].name; +e.push(n); +} +} +return e; +}, +getPublished: function() { +this.checkDefAvail(); +var e = []; +obj = this.definition.properties; +for (i = 0; i < obj.length; i++) if (obj[i].token === "published") { +p = obj[i].value[0].properties; +for (var t = 0; t < p.length; t++) { +var n = p[t].name; +e.push(n); +} +} +return e; +} +}); + +// foss/showdown-v0.9/compressed/showdown.js + +var Showdown = {}; + +Showdown.converter = function() { +var e, t, n, r = 0; +this.makeHtml = function(r) { +return e = new Array, t = new Array, n = new Array, r = r.replace(/~/g, "~T"), r = r.replace(/\$/g, "~D"), r = r.replace(/\r\n/g, "\n"), r = r.replace(/\r/g, "\n"), r = "\n\n" + r + "\n\n", r = O(r), r = r.replace(/^[ \t]+$/mg, ""), r = s(r), r = i(r), r = u(r), r = L(r), r = r.replace(/~D/g, "$$"), r = r.replace(/~T/g, "~"), r; +}; +var i = function(n) { +var n = n.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, function(n, r, i, s, o) { +return r = r.toLowerCase(), e[r] = T(i), s ? s + o : (o && (t[r] = o.replace(/"/g, """)), ""); +}); +return n; +}, s = function(e) { +e = e.replace(/\n/g, "\n\n"); +var t = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del", n = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"; +return e = e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, o), e = e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, o), e = e.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, o), e = e.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g, o), e = e.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, o), e = e.replace(/\n\n/g, "\n"), e; +}, o = function(e, t) { +var r = t; +return r = r.replace(/\n\n/g, "\n"), r = r.replace(/^\n/, ""), r = r.replace(/\n+$/g, ""), r = "\n\n~K" + (n.push(r) - 1) + "K\n\n", r; +}, u = function(e) { +e = d(e); +var t = y("
"); +return e = e.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, t), e = e.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, t), e = e.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, t), e = m(e), e = g(e), e = S(e), e = s(e), e = x(e), e; +}, a = function(e) { +return e = b(e), e = f(e), e = N(e), e = h(e), e = l(e), e = C(e), e = T(e), e = E(e), e = e.replace(/ +\n/g, "
\n"), e; +}, f = function(e) { +var t = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; +return e = e.replace(t, function(e) { +var t = e.replace(/(.)<\/?code>(?=.)/g, "$1`"); +return t = M(t, "\\`*_"), t; +}), e; +}, l = function(e) { +return e = e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, c), e = e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, c), e = e.replace(/(\[([^\[\]]+)\])()()()()()/g, c), e; +}, c = function(n, r, i, s, o, u, a, f) { +f == undefined && (f = ""); +var l = r, c = i, h = s.toLowerCase(), p = o, d = f; +if (p == "") { +h == "" && (h = c.toLowerCase().replace(/ ?\n/g, " ")), p = "#" + h; +if (e[h] != undefined) p = e[h], t[h] != undefined && (d = t[h]); else { +if (!(l.search(/\(\s*\)$/m) > -1)) return l; +p = ""; +} +} +p = M(p, "*_"); +var v = '", v; +}, h = function(e) { +return e = e.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, p), e = e.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, p), e; +}, p = function(n, r, i, s, o, u, a, f) { +var l = r, c = i, h = s.toLowerCase(), p = o, d = f; +d || (d = ""); +if (p == "") { +h == "" && (h = c.toLowerCase().replace(/ ?\n/g, " ")), p = "#" + h; +if (e[h] == undefined) return l; +p = e[h], t[h] != undefined && (d = t[h]); +} +c = c.replace(/"/g, """), p = M(p, "*_"); +var v = '' + c + '" + a(t) + ""); +}), e = e.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, function(e, t) { +return y("

" + a(t) + "

"); +}), e = e.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, function(e, t, n) { +var r = t.length; +return y("" + a(n) + ""); +}), e; +}, v, m = function(e) { +e += "~0"; +var t = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; +return r ? e = e.replace(t, function(e, t, n) { +var r = t, i = n.search(/[*+-]/g) > -1 ? "ul" : "ol"; +r = r.replace(/\n{2,}/g, "\n\n\n"); +var s = v(r); +return s = s.replace(/\s+$/, ""), s = "<" + i + ">" + s + "\n", s; +}) : (t = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g, e = e.replace(t, function(e, t, n, r) { +var i = t, s = n, o = r.search(/[*+-]/g) > -1 ? "ul" : "ol", s = s.replace(/\n{2,}/g, "\n\n\n"), u = v(s); +return u = i + "<" + o + ">\n" + u + "\n", u; +})), e = e.replace(/~0/, ""), e; +}; +v = function(e) { +return r++, e = e.replace(/\n{2,}$/, "\n"), e += "~0", e = e.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, function(e, t, n, r, i) { +var s = i, o = t, f = n; +return o || s.search(/\n{2,}/) > -1 ? s = u(A(s)) : (s = m(A(s)), s = s.replace(/\n$/, ""), s = a(s)), "
  • " + s + "
  • \n"; +}), e = e.replace(/~0/g, ""), r--, e; +}; +var g = function(e) { +return e += "~0", e = e.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g, function(e, t, n) { +var r = t, i = n; +return r = w(A(r)), r = O(r), r = r.replace(/^\n+/g, ""), r = r.replace(/\n+$/g, ""), r = "
    " + r + "\n
    ", y(r) + i; +}), e = e.replace(/~0/, ""), e; +}, y = function(e) { +return e = e.replace(/(^\n+|\n+$)/g, ""), "\n\n~K" + (n.push(e) - 1) + "K\n\n"; +}, b = function(e) { +return e = e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function(e, t, n, r, i) { +var s = r; +return s = s.replace(/^([ \t]*)/g, ""), s = s.replace(/[ \t]*$/g, ""), s = w(s), t + "" + s + ""; +}), e; +}, w = function(e) { +return e = e.replace(/&/g, "&"), e = e.replace(//g, ">"), e = M(e, "*_{}[]\\", !1), e; +}, E = function(e) { +return e = e.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, "$2"), e = e.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, "$2"), e; +}, S = function(e) { +return e = e.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, function(e, t) { +var n = t; +return n = n.replace(/^[ \t]*>[ \t]?/gm, "~0"), n = n.replace(/~0/g, ""), n = n.replace(/^[ \t]+$/gm, ""), n = u(n), n = n.replace(/(^|\n)/g, "$1 "), n = n.replace(/(\s*
    [^\r]+?<\/pre>)/gm, function(e, t) {
    +var n = t;
    +return n = n.replace(/^  /mg, "~0"), n = n.replace(/~0/g, ""), n;
    +}), y("
    \n" + n + "\n
    "); +}), e; +}, x = function(e) { +e = e.replace(/^\n+/g, ""), e = e.replace(/\n+$/g, ""); +var t = e.split(/\n{2,}/g), r = new Array, i = t.length; +for (var s = 0; s < i; s++) { +var o = t[s]; +o.search(/~K(\d+)K/g) >= 0 ? r.push(o) : o.search(/\S/) >= 0 && (o = a(o), o = o.replace(/^([ \t]*)/g, "

    "), o += "

    ", r.push(o)); +} +i = r.length; +for (var s = 0; s < i; s++) while (r[s].search(/~K(\d+)K/) >= 0) { +var u = n[RegExp.$1]; +u = u.replace(/\$/g, "$$$$"), r[s] = r[s].replace(/~K\d+K/, u); +} +return r.join("\n\n"); +}, T = function(e) { +return e = e.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&"), e = e.replace(/<(?![a-z\/?\$!])/gi, "<"), e; +}, N = function(e) { +return e = e.replace(/\\(\\)/g, _), e = e.replace(/\\([`*_{}\[\]()>#+-.!])/g, _), e; +}, C = function(e) { +return e = e.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '
    $1'), e = e.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, function(e, t) { +return k(L(t)); +}), e; +}, k = function(e) { +function t(e) { +var t = "0123456789ABCDEF", n = e.charCodeAt(0); +return t.charAt(n >> 4) + t.charAt(n & 15); +} +var n = [ function(e) { +return "&#" + e.charCodeAt(0) + ";"; +}, function(e) { +return "&#x" + t(e) + ";"; +}, function(e) { +return e; +} ]; +return e = "mailto:" + e, e = e.replace(/./g, function(e) { +if (e == "@") e = n[Math.floor(Math.random() * 2)](e); else if (e != ":") { +var t = Math.random(); +e = t > .9 ? n[2](e) : t > .45 ? n[1](e) : n[0](e); +} +return e; +}), e = '' + e + "", e = e.replace(/">.+:/g, '">'), e; +}, L = function(e) { +return e = e.replace(/~E(\d+)E/g, function(e, t) { +var n = parseInt(t); +return String.fromCharCode(n); +}), e; +}, A = function(e) { +return e = e.replace(/^(\t|[ ]{1,4})/gm, "~0"), e = e.replace(/~0/g, ""), e; +}, O = function(e) { +return e = e.replace(/\t(?=\t)/g, " "), e = e.replace(/\t/g, "~A~B"), e = e.replace(/~B(.+?)~A/g, function(e, t, n) { +var r = t, i = 4 - r.length % 4; +for (var s = 0; s < i; s++) r += " "; +return r; +}), e = e.replace(/~A/g, " "), e = e.replace(/~B/g, ""), e; +}, M = function(e, t, n) { +var r = "([" + t.replace(/([\[\]\\])/g, "\\$1") + "])"; +n && (r = "\\\\" + r); +var i = new RegExp(r, "g"); +return e = e.replace(i, _), e; +}, _ = function(e, t) { +var n = t.charCodeAt(0); +return "~E" + n + "E"; +}; +}; + +// foss/syntaxhighlighter_3.0.83_fork/sh-min.js + +var XRegExp; + +if (XRegExp) throw Error("can't load XRegExp twice in the same frame"); + +(function() { +function e(e, n) { +if (!XRegExp.isRegExp(e)) throw TypeError("type RegExp expected"); +var r = e._xregexp; +return e = XRegExp(e.source, t(e) + (n || "")), r && (e._xregexp = { +source: r.source, +captureNames: r.captureNames ? r.captureNames.slice(0) : null +}), e; +} +function t(e) { +return (e.global ? "g" : "") + (e.ignoreCase ? "i" : "") + (e.multiline ? "m" : "") + (e.extended ? "x" : "") + (e.sticky ? "y" : ""); +} +function n(e, t, n, r) { +var i = a.length, s, o, f; +u = !0; +try { +while (i--) { +f = a[i]; +if (n & f.scope && (!f.trigger || f.trigger.call(r))) { +f.pattern.lastIndex = t, o = f.pattern.exec(e); +if (o && o.index === t) { +s = { +output: f.handler.call(r, o, n), +match: o +}; +break; +} +} +} +} catch (l) { +throw l; +} finally { +u = !1; +} +return s; +} +function r(e, t, n) { +if (Array.prototype.indexOf) return e.indexOf(t, n); +for (var r = n || 0; r < e.length; r++) if (e[r] === t) return r; +return -1; +} +XRegExp = function(t, r) { +var i = [], o = XRegExp.OUTSIDE_CLASS, a = 0, l, c, h, p, v; +if (XRegExp.isRegExp(t)) { +if (r !== undefined) throw TypeError("can't supply flags when constructing one RegExp from another"); +return e(t); +} +if (u) throw Error("can't call the XRegExp constructor within token definition functions"); +r = r || "", l = { +hasNamedCapture: !1, +captureNames: [], +hasFlag: function(e) { +return r.indexOf(e) > -1; +}, +setFlag: function(e) { +r += e; +} +}; +while (a < t.length) c = n(t, a, o, l), c ? (i.push(c.output), a += c.match[0].length || 1) : (h = f.exec.call(d[o], t.slice(a))) ? (i.push(h[0]), a += h[0].length) : (p = t.charAt(a), p === "[" ? o = XRegExp.INSIDE_CLASS : p === "]" && (o = XRegExp.OUTSIDE_CLASS), i.push(p), a++); +return v = RegExp(i.join(""), f.replace.call(r, s, "")), v._xregexp = { +source: t, +captureNames: l.hasNamedCapture ? l.captureNames : null +}, v; +}, XRegExp.version = "1.5.0", XRegExp.INSIDE_CLASS = 1, XRegExp.OUTSIDE_CLASS = 2; +var i = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g, s = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, o = /^(?:[?*+]|{\d+(?:,\d*)?})\??/, u = !1, a = [], f = { +exec: RegExp.prototype.exec, +test: RegExp.prototype.test, +match: String.prototype.match, +replace: String.prototype.replace, +split: String.prototype.split +}, l = f.exec.call(/()??/, "")[1] === undefined, c = function() { +var e = /^/g; +return f.test.call(e, ""), !e.lastIndex; +}(), h = function() { +var e = /x/g; +return f.replace.call("x", e, ""), !e.lastIndex; +}(), p = RegExp.prototype.sticky !== undefined, d = {}; +d[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/, d[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/, XRegExp.addToken = function(t, n, r, i) { +a.push({ +pattern: e(t, "g" + (p ? "y" : "")), +handler: n, +scope: r || XRegExp.OUTSIDE_CLASS, +trigger: i || null +}); +}, XRegExp.cache = function(e, t) { +var n = e + "/" + (t || ""); +return XRegExp.cache[n] || (XRegExp.cache[n] = XRegExp(e, t)); +}, XRegExp.copyAsGlobal = function(t) { +return e(t, "g"); +}, XRegExp.escape = function(e) { +return e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +}, XRegExp.execAt = function(t, n, r, i) { +n = e(n, "g" + (i && p ? "y" : "")), n.lastIndex = r = r || 0; +var s = n.exec(t); +return i ? s && s.index === r ? s : null : s; +}, XRegExp.freezeTokens = function() { +XRegExp.addToken = function() { +throw Error("can't run addToken after freezeTokens"); +}; +}, XRegExp.isRegExp = function(e) { +return Object.prototype.toString.call(e) === "[object RegExp]"; +}, XRegExp.iterate = function(t, n, r, i) { +var s = e(n, "g"), o = -1, u; +while (u = s.exec(t)) r.call(i, u, ++o, t, s), s.lastIndex === u.index && s.lastIndex++; +n.global && (n.lastIndex = 0); +}, XRegExp.matchChain = function(t, n) { +return function r(t, i) { +var s = n[i].regex ? n[i] : { +regex: n[i] +}, o = e(s.regex, "g"), u = [], a; +for (a = 0; a < t.length; a++) XRegExp.iterate(t[a], o, function(e) { +u.push(s.backref ? e[s.backref] || "" : e[0]); +}); +return i === n.length - 1 || !u.length ? u : r(u, i + 1); +}([ t ], 0); +}, RegExp.prototype.apply = function(e, t) { +return this.exec(t[0]); +}, RegExp.prototype.call = function(e, t) { +return this.exec(t); +}, RegExp.prototype.exec = function(e) { +var n = f.exec.apply(this, arguments), i, s; +if (n) { +!l && n.length > 1 && r(n, "") > -1 && (s = RegExp(this.source, f.replace.call(t(this), "g", "")), f.replace.call(e.slice(n.index), s, function() { +for (var e = 1; e < arguments.length - 2; e++) arguments[e] === undefined && (n[e] = undefined); +})); +if (this._xregexp && this._xregexp.captureNames) for (var o = 1; o < n.length; o++) i = this._xregexp.captureNames[o - 1], i && (n[i] = n[o]); +!c && this.global && !n[0].length && this.lastIndex > n.index && this.lastIndex--; +} +return n; +}, c || (RegExp.prototype.test = function(e) { +var t = f.exec.call(this, e); +return t && this.global && !t[0].length && this.lastIndex > t.index && this.lastIndex--, !!t; +}), String.prototype.match = function(e) { +XRegExp.isRegExp(e) || (e = RegExp(e)); +if (e.global) { +var t = f.match.apply(this, arguments); +return e.lastIndex = 0, t; +} +return e.exec(this); +}, String.prototype.replace = function(e, t) { +var n = XRegExp.isRegExp(e), s, o, u; +return n && typeof t.valueOf() == "string" && t.indexOf("${") === -1 && h ? f.replace.apply(this, arguments) : (n ? e._xregexp && (s = e._xregexp.captureNames) : e += "", typeof t == "function" ? o = f.replace.call(this, e, function() { +if (s) { +arguments[0] = new String(arguments[0]); +for (var r = 0; r < s.length; r++) s[r] && (arguments[0][s[r]] = arguments[r + 1]); +} +return n && e.global && (e.lastIndex = arguments[arguments.length - 2] + arguments[0].length), t.apply(null, arguments); +}) : (u = this + "", o = f.replace.call(u, e, function() { +var e = arguments; +return f.replace.call(t, i, function(t, n, i) { +if (!n) { +var o = +i; +return o <= e.length - 3 ? e[o] : (o = s ? r(s, i) : -1, o > -1 ? e[o + 1] : t); +} +switch (n) { +case "$": +return "$"; +case "&": +return e[0]; +case "`": +return e[e.length - 1].slice(0, e[e.length - 2]); +case "'": +return e[e.length - 1].slice(e[e.length - 2] + e[0].length); +default: +var u = ""; +n = +n; +if (!n) return t; +while (n > e.length - 3) u = String.prototype.slice.call(n, -1) + u, n = Math.floor(n / 10); +return (n ? e[n] || "" : "$") + u; +} +}); +})), n && e.global && (e.lastIndex = 0), o); +}, String.prototype.split = function(e, t) { +if (!XRegExp.isRegExp(e)) return f.split.apply(this, arguments); +var n = this + "", r = [], i = 0, s, o; +if (t === undefined || +t < 0) t = Infinity; else { +t = Math.floor(+t); +if (!t) return []; +} +e = XRegExp.copyAsGlobal(e); +while (s = e.exec(n)) { +if (e.lastIndex > i) { +r.push(n.slice(i, s.index)), s.length > 1 && s.index < n.length && Array.prototype.push.apply(r, s.slice(1)), o = s[0].length, i = e.lastIndex; +if (r.length >= t) break; +} +e.lastIndex === s.index && e.lastIndex++; +} +return i === n.length ? (!f.test.call(e, "") || o) && r.push("") : r.push(n.slice(i)), r.length > t ? r.slice(0, t) : r; +}, XRegExp.addToken(/\(\?#[^)]*\)/, function(e) { +return f.test.call(o, e.input.slice(e.index + e[0].length)) ? "" : "(?:)"; +}), XRegExp.addToken(/\((?!\?)/, function() { +return this.captureNames.push(null), "("; +}), XRegExp.addToken(/\(\?<([$\w]+)>/, function(e) { +return this.captureNames.push(e[1]), this.hasNamedCapture = !0, "("; +}), XRegExp.addToken(/\\k<([\w$]+)>/, function(e) { +var t = r(this.captureNames, e[1]); +return t > -1 ? "\\" + (t + 1) + (isNaN(e.input.charAt(e.index + e[0].length)) ? "" : "(?:)") : e[0]; +}), XRegExp.addToken(/\[\^?]/, function(e) { +return e[0] === "[]" ? "\\b\\B" : "[\\s\\S]"; +}), XRegExp.addToken(/^\(\?([imsx]+)\)/, function(e) { +return this.setFlag(e[1]), ""; +}), XRegExp.addToken(/(?:\s+|#.*)+/, function(e) { +return f.test.call(o, e.input.slice(e.index + e[0].length)) ? "" : "(?:)"; +}, XRegExp.OUTSIDE_CLASS, function() { +return this.hasFlag("x"); +}), XRegExp.addToken(/\./, function() { +return "[\\s\\S]"; +}, XRegExp.OUTSIDE_CLASS, function() { +return this.hasFlag("s"); +}); +})(); + +var SyntaxHighlighter = function() { +function e(e) { +return e.split("\n"); +} +function t(e, t, n) { +n = Math.max(n || 0, 0); +for (var r = n; r < e.length; r++) if (e[r] == t) return r; +return -1; +} +function n(e, t) { +var n = {}, r; +for (r in e) n[r] = e[r]; +for (r in t) n[r] = t[r]; +return n; +} +function r(e) { +var t = { +"true": !0, +"false": !1 +}[e]; +return t == null ? e : t; +} +function i(t, n) { +var r = e(t); +for (var i = 0; i < r.length; i++) r[i] = n(r[i], i); +return r.join("\n"); +} +function s(e) { +return e.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, ""); +} +function o(e, t) { +return e == null || e.length == 0 || e == "\n" ? e : (e = e.replace(/' + e + ""; +})), e); +} +function u(e, t) { +var n = e.toString(); +while (n.length < t) n = "0" + n; +return n; +} +function a(e, t) { +var n = ""; +for (var r = 0; r < t; r++) n += " "; +return e.replace(/\t/g, n); +} +function f(t, n) { +function r(e, t, n) { +return e.substr(0, t) + u.substr(0, n) + e.substr(t + 1, e.length); +} +var s = e(t), o = " ", u = ""; +for (var a = 0; a < 50; a++) u += " "; +return t = i(t, function(e) { +if (e.indexOf(o) == -1) return e; +var t = 0; +while ((t = e.indexOf(o)) != -1) { +var i = n - t % n; +e = r(e, t, i); +} +return e; +}), t; +} +function l(e) { +var t = /|<br\s*\/?>/gi; +return e = e.replace(t, "\n"), m.config.stripBrs == 1 && (e = e.replace(t, "")), e; +} +function c(e) { +return e.replace(/^\s+|\s+$/g, ""); +} +function h(t) { +var n = e(l(t)), r = new Array, i = /^\s*/, s = 1e3; +for (var o = 0; o < n.length && s > 0; o++) { +var u = n[o]; +if (c(u).length == 0) continue; +var a = i.exec(u); +if (a == null) return t; +s = Math.min(a[0].length, s); +} +if (s > 0) for (var o = 0; o < n.length; o++) n[o] = n[o].substr(s); +return n.join("\n"); +} +function p(e, t) { +return e.index < t.index ? -1 : e.index > t.index ? 1 : e.length < t.length ? -1 : e.length > t.length ? 1 : 0; +} +function d(e, t) { +function n(e, t) { +return e[0]; +} +var r = 0, i = null, s = [], o = t.func ? t.func : n; +while ((i = t.regex.exec(e)) != null) { +var u = o(i, t); +typeof u == "string" && (u = [ new m.Match(u, i.index, t.css) ]), s = s.concat(u); +} +return s; +} +function v(e) { +var t = /(.*)((>|<).*)/; +return e.replace(m.regexLib.url, function(e) { +var n = "", r = null; +if (r = t.exec(e)) e = r[1], n = r[2]; +return '' + e + "" + n; +}); +} +var m = { +defaults: { +"class-name": "", +"first-line": 1, +"pad-line-numbers": !1, +highlight: null, +"smart-tabs": !0, +"tab-size": 4, +gutter: !0, +"auto-links": !0 +}, +config: { +space: " ", +stripBrs: !1, +strings: { +alert: "SyntaxHighlighter\n\n", +noBrush: "Can't find brush for: ", +brushNotHtmlScript: "Brush wasn't configured for html-script option: " +} +}, +brushes: {}, +regexLib: { +multiLineCComments: /\/\*[\s\S]*?\*\//gm, +singleLineCComments: /\/\/.*$/gm, +singleLinePerlComments: /#.*$/gm, +doubleQuotedString: /"([^\\"\n]|\\.)*"/g, +singleQuotedString: /'([^\\'\n]|\\.)*'/g, +multiLineDoubleQuotedString: new XRegExp('"([^\\\\"]|\\\\.)*"', "gs"), +multiLineSingleQuotedString: new XRegExp("'([^\\\\']|\\\\.)*'", "gs"), +xmlComments: /(<|<)!--[\s\S]*?--(>|>)/gm, +url: /\w+:\/\/[\w-.\/?%&=:@;]*/g, +phpScriptTags: { +left: /(<|<)\?=?/g, +right: /\?(>|>)/g +}, +aspScriptTags: { +left: /(<|<)%=?/g, +right: /%(>|>)/g +}, +scriptScriptTags: { +left: /(<|<)\s*script.*?(>|>)/gi, +right: /(<|<)\/\s*script\s*(>|>)/gi +} +} +}; +return m.Match = function(e, t, n) { +this.value = e, this.index = t, this.length = e.length, this.css = n, this.brushName = null; +}, m.Match.prototype.toString = function() { +return this.value; +}, m.Highlighter = function() {}, m.Highlighter.prototype = { +getParam: function(e, t) { +var n = this.params[e]; +return r(n == null ? t : n); +}, +create: function(e) { +return document.createElement(e); +}, +findMatches: function(e, t) { +var n = []; +if (e != null) for (var r = 0; r < e.length; r++) typeof e[r] == "object" && (n = n.concat(d(t, e[r]))); +return this.removeNestedMatches(n.sort(p)); +}, +removeNestedMatches: function(e) { +for (var t = 0; t < e.length; t++) { +if (e[t] === null) continue; +var n = e[t], r = n.index + n.length; +for (var i = t + 1; i < e.length && e[t] !== null; i++) { +var s = e[i]; +if (s === null) continue; +if (s.index > r) break; +s.index == n.index && s.length > n.length ? e[t] = null : s.index >= n.index && s.index < r && (e[i] = null); +} +} +return e; +}, +figureOutLineNumbers: function(e) { +var t = [], n = parseInt(this.getParam("first-line")); +return i(e, function(e, r) { +t.push(r + n); +}), t; +}, +isLineHighlighted: function(e) { +var n = this.getParam("highlight", []); +return typeof n != "object" && n.push == null && (n = [ n ]), t(n, e.toString()) != -1; +}, +getLineHtml: function(e, t, n) { +var r = [ "line", "number" + t, "index" + e, "alt" + (t % 2 == 0 ? 1 : 2).toString() ]; +return this.isLineHighlighted(t) && r.push("highlighted"), t == 0 && r.push("break"), '
    ' + n + "
    "; +}, +getLineNumbersHtml: function(t, n) { +var r = "", i = e(t).length, s = parseInt(this.getParam("first-line")), o = this.getParam("pad-line-numbers"); +o == 1 ? o = (s + i - 1).toString().length : isNaN(o) == 1 && (o = 0); +for (var a = 0; a < i; a++) { +var f = n ? n[a] : s + a, t = f == 0 ? m.config.space : u(f, o); +r += this.getLineHtml(a, f, t); +} +return r; +}, +getCodeLinesHtml: function(t, n) { +t = c(t); +var r = e(t), i = this.getParam("pad-line-numbers"), s = parseInt(this.getParam("first-line")), t = "", o = this.getParam("brush"); +for (var u = 0; u < r.length; u++) { +var a = r[u], f = /^( |\s)+/.exec(a), l = null, h = n ? n[u] : s + u; +f != null && (l = f[0].toString(), a = a.substr(l.length), l = l.replace(" ", m.config.space)), a = c(a), a.length == 0 && (a = m.config.space), t += this.getLineHtml(u, h, (l != null ? '' + l + "" : "") + a); +} +return t; +}, +getMatchesHtml: function(e, t) { +function n(e) { +var t = e ? e.brushName || s : s; +return t ? t + " " : ""; +} +var r = 0, i = "", s = this.getParam("brush", ""); +for (var u = 0; u < t.length; u++) { +var a = t[u], f; +if (a === null || a.length === 0) continue; +f = n(a), i += o(e.substr(r, a.index - r), f + "plain") + o(a.value, f + a.css), r = a.index + a.length + (a.offset || 0); +} +return i += o(e.substr(r), n() + "plain"), i; +}, +getHtml: function(e) { +var t = "", n = [ "syntaxhighlighter" ], r, i, o; +return className = "syntaxhighlighter", (gutter = this.getParam("gutter")) == 0 && n.push("nogutter"), n.push(this.getParam("class-name")), n.push(this.getParam("brush")), e = s(e).replace(/\r/g, " "), r = this.getParam("tab-size"), e = this.getParam("smart-tabs") == 1 ? f(e, r) : a(e, r), e = h(e), gutter && (o = this.figureOutLineNumbers(e)), i = this.findMatches(this.regexList, e), t = this.getMatchesHtml(e, i), t = this.getCodeLinesHtml(t, o), this.getParam("auto-links") && (t = v(t)), typeof navigator != "undefined" && navigator.userAgent && navigator.userAgent.match(/MSIE/) && n.push("ie"), t = '
    ' + '' + "" + "" + (gutter ? '" : "") + '" + "" + "" + "
    ' + this.getLineNumbersHtml(e) + "' + '
    ' + t + "
    " + "
    " + "
    ", t; +}, +init: function(e) { +this.params = n(m.defaults, e || {}); +}, +getKeywords: function(e) { +return e = e.replace(/^\s+|\s+$/g, "").replace(/\s+/g, "|"), "\\b(?:" + e + ")\\b"; +} +}, m; +}(); + +(function() { +function e() { +var e = "break case catch continue default delete do else false for function if in instanceof new null return super switch this throw true try typeof var while with", t = SyntaxHighlighter.regexLib; +this.regexList = [ { +regex: t.multiLineDoubleQuotedString, +css: "string" +}, { +regex: t.multiLineSingleQuotedString, +css: "string" +}, { +regex: t.singleLineCComments, +css: "comments" +}, { +regex: t.multiLineCComments, +css: "comments" +}, { +regex: /\s*#.*/gm, +css: "preprocessor" +}, { +regex: new RegExp(this.getKeywords(e), "gm"), +css: "keyword" +} ]; +} +e.prototype = new SyntaxHighlighter.Highlighter, e.aliases = [ "js", "jscript", "javascript" ], SyntaxHighlighter.brushes.JScript = e; +})(), function() { +var e = new SyntaxHighlighter.brushes.JScript; +e.init({}), syntaxHighlight = function(t) { +return e.getHtml(t); +}; +}(); + +// Presentor.js + +enyo.kind({ +name: "Presentor", +kind: null, +showInherited: !1, +showProtected: !1, +getByType: function(e, t) { +var n = []; +for (var r = 0, i; i = e[r]; r++) i.type == t && n.push(i); +return n; +}, +presentObject: function(e) { +switch (e.type) { +case "module": +return this.presentObjects(e.objects); +case "kind": +return this.presentKind(e); +case "function": +case "global": +return this.presentProperty(e); +} +}, +presentObjects: function(e) { +var t = this.groupFilter(e), n = "", r, i, s = !1, o = this.getByType(t, "kind"); +if (o.length) { +n += "

    Kinds

    "; +for (r = 0; i = o[r]; r++) n += "" + i.name + "
    ", n += this.presentComment(i.comment); +s = !0; +} +o = this.getByType(t, "function"); +if (o.length) { +n += "

    Functions

    "; +for (r = 0; i = o[r]; r++) i.group && (n += "<" + i.group + ">" + i.group + ""), n += ": function(" + i.value[0].arguments.join(", ") + ")
    ", n += this.presentComment(i.comment); +s = !0; +} +o = this.getByType(t, "global"); +if (o.length) { +n += "

    Variables

    "; +for (r = 0; i = o[r]; r++) n += this.presentComment(i.comment), i.group && (n += "<" + i.group + ">" + i.group + ""), n += " = ", n += this.presentExpression(i.value[0]), n += "
    "; +s = !0; +} +return s || (n += "

    This module has no public properties or functions to display.

    "), n; +}, +presentComment: function(e) { +return e ? "" + this.markupToHtml(e) + "" : ""; +}, +presentKind: function(e) { +return this.presentKindHeader(e) + this.presentKindSummary(e) + this.presentKindProperties(e); +}, +presentKindHeader: function(e) { +var t = ""; +return e.module && e.module.label && (t += "" + e.module.label + ""), t += "" + e.name + "", e.superkinds.length && (t += '
    ', t += e.name, enyo.forEach(e.superkinds, function(e) { +t += " :: " + e + ""; +}), t += "
    "), t; +}, +presentKindSummary: function(e) { +var t = ""; +return e.comment && (t += "

    Summary

    " + this.presentComment(e.comment)), t; +}, +presentKindProperties: function(e) { +return this.presentProperties(this.showInherited ? e.allProperties : e.properties, e); +}, +groupFilter: function(e) { +return enyo.filter(e, function(e) { +return e.name[0] !== "_" && (e.group == "public" || this.showProtected && e.group == "protected"); +}, this); +}, +presentProperties: function(e, t) { +var n = this.groupFilter(e), r = ""; +for (var i = 0, s; s = n[i]; i++) r += this.presentProperty(s, t); +return r; +}, +presentProperty: function(e, t) { +var n = "", r = e; +n += '', r.group && (n += "<" + r.group + ">" + r.group + ""); +var i = r.name.replace(".prototype", ""); +return r.object && t && t != r.object && (i = "" + r.object.name + "::" + i), n += ": ", r.value && r.value[0] && r.value[0].token == "function" ? n += "function(" + r.value[0].arguments.join(", ") + ")
    " : n += this.presentValue(r), n += this.presentComment(r.comment), n += "
    ", n; +}, +presentValue: function(e) { +var t, n = e.value; +return !n || !n[0] ? t = e.token : t = this.presentExpression(n[0]), t += "
    ", t; +}, +presentExpression: function(e) { +var t = e; +return t.comment ? this.presentComment(t.comment) : t.type == "block" ? "{

    " + this.presentBlock(t) + "
    }" : t.type == "array" ? "[
    " + this.presentArray(t) + "
    ]" : t.token; +}, +presentBlock: function(e) { +return this.presentProperties(e.properties); +}, +presentArray: function(e) { +var t = "", n = e.properties; +for (var r = 0, i; i = n[r]; r++) t += "" + r + ": " + this.presentExpression(i); +return t; +}, +presentColumns: function(e, t, n) { +var r = this.groupFilter(e), i = ""; +t && (i = t.name + "::"); +var s = n || 4, o = [], u = ""; +for (var a = 0, f = 0, l = 0; p = r[a]; a++) u += '' + p.name + "
    ", ++l == s && (o.push(u), u = "", l = 0); +return u && o.push(u), u = o.length ? "" + o.join("") + "" : "", u; +}, +markupToHtml: function(e) { +var t = Presentor.showdown.makeHtml(e || ""); +return t = t.replace(/
    ([\s\S]*?)<\/code><\/pre>/gm, function(e, t) {
    +return "
    " + syntaxHighlight(t) + "
    "; +}), t; +}, +inlineProperties: function(e, t) { +var n = [], r = function(e) { +e.parentHash = s.name; +}; +for (var i = 0, s; s = e[i]; i++) t[s.name] ? s.value && s.value[0] && s.value[0].properties && (enyo.forEach(s.value[0].properties, r), n = n.concat(s.value[0].properties)) : n.push(s); +return n; +}, +statics: { +showdown: new Showdown.converter +} +}); + +// PackagesEditor.js + +enyo.kind({ +name: "PackagesEditor", +kind: "Popup", +classes: "packages-editor", +events: { +onSave: "" +}, +components: [ { +kind: "Repeater", +onSetupItem: "setupItem", +components: [ { +components: [ { +name: "name", +kind: "Input" +}, { +name: "path", +kind: "Input" +}, { +kind: "Button", +content: "Delete", +ontap: "deletePkg" +} ] +} ] +}, { +kind: "Button", +content: "New...", +ontap: "newPkg" +}, { +tag: "hr" +}, { +kind: "Button", +content: "Cancel", +ontap: "hide" +}, { +kind: "Button", +content: "Save", +ontap: "save" +} ], +openWithPackages: function(e) { +this.show(), this.pkgs = e, this.load(); +}, +load: function() { +this.$.repeater.setCount(this.pkgs.length); +}, +setupItem: function(e, t) { +var n = this.pkgs[t.index]; +return t.item.$.name.setValue(n.name), t.item.$.path.setValue(n.path), !0; +}, +newPkg: function() { +this.pkgs.push({ +name: "", +path: "" +}), this.load(); +}, +deletePkg: function(e, t) { +this.pkgs.splice(t.index, 1), this.load(); +}, +save: function() { +var e = []; +for (var t = 0, n; n = this.$.repeater.getClientControls()[t]; t++) { +var r = n.$.name.getValue(), i = n.$.path.getValue(); +r && i && e.push({ +name: r, +path: i +}); +} +this.doSave({ +pkgs: e +}), this.hide(); +} +}); + +// PackageList.js + +enyo.kind({ +name: "PackageList", +components: [ { +kind: "Repeater", +components: [ { +components: [ { +kind: "Checkbox", +onchange: "cbChange" +} ] +} ] +}, { +name: "version", +style: "padding-top: 20px" +}, { +kind: "PackagesEditor", +modal: !0, +centered: !0, +floating: !0, +onSave: "savePackages" +} ], +published: { +version: "" +}, +events: { +onPackagesChange: "", +onLoaded: "" +}, +handlers: { +onSetupItem: "setupItem" +}, +create: function() { +this.inherited(arguments), this.versionChanged(); +}, +versionChanged: function() { +this.$.version.setContent("Content Version: " + this.version); +}, +fetchPackageData: function() { +(new enyo.Ajax({ +url: "assets/manifest.json" +})).response(this, function(e, t) { +this.setVersion(t.version), this.gotPackageData(t.packages); +}).go(); +}, +gotPackageData: function(e) { +this.pkgs = e, this.$.repeater.setCount(this.pkgs.length), this.doLoaded({ +packages: this.pkgs, +version: this.version +}); +}, +loadPackageData: function() { +this.pkgs ? this.gotPackageData(this.pkgs) : this.fetchPackageData(); +}, +savePackageData: function() {}, +setupItem: function(e, t) { +var n = this.pkgs[t.index], r = t.item.$.checkbox; +r.setContent(n.name), r.setChecked(!n.disabled); +}, +cbChange: function(e, t) { +var n = t.index, r = this.pkgs[n]; +r && (r.disabled = !e.getChecked(), this.savePackageData()), this.doPackagesChange({ +pkg: r +}); +} +}); + +// TabPanels.js + +enyo.kind({ +name: "TabPanels", +kind: "FittableRows", +components: [ { +name: "tabs", +kind: "Group", +defaultKind: "Button", +controlClasses: "tab" +}, { +name: "client", +style: "position: relative;", +fit: !0 +} ], +create: function() { +this.inherited(arguments), this.selectTab(0); +}, +addControl: function(e) { +e.isChrome || (e.addClass("enyo-fit"), e.showing = !1, this.$.tabs.createComponent({ +content: e.tabName || e.name, +ontap: "tabTap", +owner: this +})), this.inherited(arguments); +}, +selectTab: function(e) { +this.$.tabs.getControls()[e].setActive(!0); +for (var t = 0, n = this.getClientControls(), r; r = n[t]; t++) r.setShowing(t == e); +}, +tabTap: function(e) { +this.selectTab(e.indexInContainer()); +} +}); + +// SearchBar.js + +enyo.kind({ +name: "SearchBar", +events: { +onSearch: "" +}, +handlers: { +onkeyup: "search", +onchange: "search" +}, +components: [ { +xkind: "InputDecorator", +classes: "enyo-tool-decorator input-decorator", +style: "display: block;", +components: [ { +kind: "Input", +style: "width: 90%;" +}, { +kind: "Image", +src: "assets/search-input-search.png" +} ] +} ], +getValue: function() { +if (this.$.input.hasNode()) return this.$.input.node.value; +}, +search: function() { +this.doSearch({ +searchString: this.getValue() +}); +} +}); + +// App.js + +enyo.kind({ +name: "App", +fit: !0, +kind: "FittableColumns", +components: [ { +kind: "Analyzer", +onIndexReady: "indexReady" +}, { +name: "left", +kind: "TabPanels", +classes: "enyo-unselectable", +components: [ { +kind: "Scroller", +tabName: "Kinds", +components: [ { +name: "kinds", +allowHtml: !0 +} ] +}, { +kind: "Scroller", +tabName: "Modules", +components: [ { +name: "modules", +allowHtml: !0 +} ] +}, { +kind: "Scroller", +tabName: "Index", +components: [ { +kind: "SearchBar", +onSearch: "search" +}, { +name: "index", +allowHtml: !0 +} ] +}, { +name: "packages", +tabName: "Packages", +kind: "PackageList", +onPackagesChange: "loadPackages", +onLoaded: "packagesLoaded" +} ] +}, { +name: "doc", +kind: "FittableRows", +fit: !0, +components: [ { +name: "scope", +components: [ { +name: "inheritedCb", +kind: "Checkbox", +content: "show inherited", +onchange: "scopeChange" +}, { +name: "accessCb", +kind: "Checkbox", +content: "show protected", +style: "margin-left: 20px;", +onchange: "accessChange" +} ] +}, { +name: "header", +allowHtml: !0 +}, { +name: "tocFrame", +kind: "Scroller", +components: [ { +name: "toc", +allowHtml: !0 +} ] +}, { +name: "bodyFrame", +kind: "Scroller", +fit: !0, +classes: "enyo-selectable", +components: [ { +name: "indexBusy", +kind: "Image", +src: "assets/busy.gif", +style: "padding-left: 8px;", +showing: !1 +}, { +name: "body", +allowHtml: !0 +} ] +} ] +} ], +create: function() { +this.inherited(arguments), window.onhashchange = enyo.bind(this, "hashChange"), this.presentor = new Presentor, this.loadPackages(); +}, +loadPackages: function() { +this.index = this.$.analyzer.index = new Indexer, this.$.packages.loadPackageData(); +}, +packagesLoaded: function(e, t) { +document.title = "Enyo API Viewer (" + t.version + ")"; +var n = []; +return enyo.forEach(t.packages, function(e) { +e.disabled || n.push({ +path: e.path, +label: e.name +}); +}), this.walk(n), !0; +}, +walk: function(e) { +this.walking = !0, this.$.indexBusy.show(), this.$.analyzer.walk(e); +}, +indexReady: function() { +this.presentKinds(), this.presentModules(), this.presentIndex(), this.$.indexBusy.hide(), this.walking = !1, this.hashChange(); +}, +indexalize: function(e, t, n) { +var r = e ? enyo.filter(this.index.objects, e, this) : this.index.objects; +e(r[0]) && r.sort(this.moduleCompare), r = this.nameFilter(r); +var i = "", s; +for (var o = 0, u; u = r[o]; o++) { +var a = n(u).divider; +a && s != a && (s = a, i += "" + a + ""), i += enyo.macroize(t, n(u)); +} +return i; +}, +moduleCompare: function(e, t) { +var n, r; +try { +n = e.name.match("[^/]*.js$")[0], r = t.name.match("[^/]*.js$")[0]; +} catch (i) { +n = e.name, r = t.name; +} +return n.toUpperCase() < r.toUpperCase() ? -1 : n.toUpperCase() > r.toUpperCase() ? 1 : 0; +}, +nameFilter: function(e) { +return enyo.filter(e, function(e) { +return e.name && e.name[0] !== "_"; +}); +}, +presentFilteredIndex: function(e) { +var t = '{$object}{$topic}{$module}
    ', n = function(e) { +return { +link: e.topic || e.name, +topic: e.name.replace(".prototype", ""), +divider: e.name[0].toUpperCase(), +object: e.object && e.object.name ? e.object.name + "::" : "", +module: !e.object && e.module && e.module.name ? " [" + e.module.name.match("[^/]*.js$") + "]" : "" +}; +}; +this.$.index.setContent(this.indexalize(e, t, n)); +}, +presentIndex: function() { +var e = function(e) { +return e.name !== "published" && (e.group == "public" || e.group == "published"); +}; +this.presentFilteredIndex(e); +}, +presentModules: function() { +var e = function(e) { +return e.type == "module"; +}, t = '{$topic}
    ', n = function(e) { +return { +link: e.topic || e.name, +topic: e.name.match("[^/]*.js$"), +divider: e.name.match("[^/]*.js$")[0][0].toUpperCase() +}; +}; +this.$.modules.setContent(this.indexalize(e, t, n)); +}, +presentKinds: function() { +var e = function(e) { +return e.type == "kind" && e.group == "public"; +}, t = '{$topic}
    ', n = function(e) { +return { +link: e.topic || e.name, +topic: e.name, +divider: e.name.split(".")[0] +}; +}; +this.$.kinds.setContent(this.indexalize(e, t, n)); +}, +presentObject: function(e) { +if (!e || !e.type) return; +if (e.type === "kind") { +this.$.header.show(), this.presentKind(e); +return; +} +e.type === "module" ? (this.$.header.show(), this.$.header.setContent("" + e.name + "")) : (this.$.header.hide(), this.$.header.setContent("")), this.$.toc.setContent(""), this.$.doc.reflow(); +var t = ""; +e && (t = this.presentor.presentObject(e)), this.$.body.setContent(t); +}, +presentKind: function(e) { +this.$.header.setContent(this.presentor.presentKindHeader(e)); +var t = this.presentor.showInherited ? e.allProperties : e.properties; +t = this.presentor.inlineProperties(t, { +published: 1, +statics: 1, +events: 1 +}), t.sort(Indexer.nameCompare); +var n = this.presentor.presentColumns(t, e); +this.$.toc.setContent(n); +var r = this.presentor.presentKindSummary(e), i = this.presentor.presentKindProperties(e); +i && (r += "

    Properties

    " + i), this.$.body.setContent(r), this.$.doc.reflow(); +}, +presentModule: function(e) { +this.presentObject(e); +}, +moduleTap: function(e) { +this.presentModule(e.object); +}, +objectTap: function(e) { +this.presentObject(e.object); +}, +hashChange: function(e) { +this.selectTopic(this.getHashTopic()); +}, +getHashTopic: function() { +return window.location.hash.slice(1); +}, +selectTopic: function(e) { +this.topic = e; +var t = e.split("::"), n = t.shift(), r = t.shift(), i = this.index.findByName(n) || this.index.findByName("enyo." + n); +this.topicObject != i && (this.presentObject(i), this.topicObject = i, this.$.body.container.setScrollTop(0)); +if (r) { +var s = document.getElementsByName(r)[0]; +s && s.scrollIntoView(!0); +} +}, +scopeChange: function() { +this.presentor.showInherited = this.$.inheritedCb.getValue(), this.topicObject = null, this.selectTopic(this.topic); +}, +accessChange: function() { +this.presentor.showProtected = this.$.accessCb.getValue(), this.topicObject = null, this.selectTopic(this.topic); +}, +search: function(e, t) { +this.setSearchString(t.searchString.toLowerCase()); +}, +setSearchString: function(e) { +var t = function(t) { +return t.name !== "published" && (t.group == "public" || t.group == "published") && t.name.toLowerCase().indexOf(e) >= 0; +}; +this.presentFilteredIndex(t); +} +}); diff --git a/api/build/enyo.css b/api/build/enyo.css new file mode 100644 index 0000000..6d05291 --- /dev/null +++ b/api/build/enyo.css @@ -0,0 +1,181 @@ + +/* ../source/dom/dom.css */ + +/* things we always want */ +body { + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; +} + +/* allow hw-accelerated scrolling on platforms that support it */ +body.webkitOverflowScrolling { + -webkit-overflow-scrolling: touch; +} + +/* for apps */ +.enyo-document-fit { + margin: 0; + height: 100%; + /* note: giving html overflow: auto is odd and was only ever done to avoid duplication + however, android 4.04 sometimes does not hide nodes when their display is set to none + if document is overflow auto. + */ + position: relative; +} + +.enyo-body-fit { + margin: 0; + height: 100%; + /* helps prevent ios page scroll */ + overflow: auto; + position: relative; +} + +.enyo-no-touch-action { + -ms-touch-action: none; +} + +/* reset */ + +button { + font-size: inherit; + font-family: inherit; +} +button::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* user selection */ + +.enyo-unselectable { + cursor: default; + -ms-user-select: none; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; +} + +.enyo-unselectable::selection, .enyo-unselectable ::selection { + color: transparent; +} + +.enyo-selectable { + cursor: auto; + -ms-user-select: element; + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; +} + +.enyo-selectable::selection, .enyo-selectable ::selection { + background: #3297FD; + color: #FFF; +} + +/* layout */ + +body .enyo-fit { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.enyo-clip { + overflow: hidden; +} + +.enyo-border-box { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* compositing */ + +.enyo-composite { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); +} + + +/* ../source/touch/Thumb.css */ + +.enyo-thumb { + position: absolute; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; + background: #333; + border: 1px solid #666; + opacity: 0.75; + z-index: 1; +} + +.enyo-vthumb { + top: 0; + right: 2px; + width: 4px; +} + +.enyo-hthumb { + left: 0; + bottom: 2px; + height: 4px; +} + + +/* ../source/touch/Scroller.css */ + +.enyo-scroller { + position: relative; +} + +.enyo-fit.enyo-scroller { + position: absolute; +} + +.enyo-touch-scroller { + overflow: hidden; +} + +.enyo-touch-strategy-container { + overflow: hidden; +} + +.enyo-scrollee-fit { + height: 100%; +} + +/* ../source/ui/ui.css */ + +.enyo-inline, .enyo-tool-decorator { + display: inline-block; +} + +.enyo-children-inline > *, .enyo-tool-decorator > * { + display: inline-block; +} + +.enyo-children-middle > *, .enyo-tool-decorator > * { + vertical-align: middle; +} + +.enyo-positioned { + position: relative; +} + +.enyo-fill { + position: relative; + width: 100%; + height: 100%; +} + +.enyo-popup { + position: absolute; + z-index: 10; +} diff --git a/api/build/enyo.js b/api/build/enyo.js new file mode 100644 index 0000000..e565f50 --- /dev/null +++ b/api/build/enyo.js @@ -0,0 +1,4283 @@ + +// enyo.js + +(function() { +var e = "enyo.js"; +enyo = window.enyo || {}, enyo.locateScript = function(e) { +var t = document.getElementsByTagName("script"); +for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { +i = r.getAttribute("src") || ""; +if (i.slice(-s) == e) return r.located = !0, { +path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), +node: r +}; +} +}, enyo.args = enyo.args || {}; +var t = enyo.locateScript(e); +if (t) { +enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); +for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; +} +})(); + +// ../../loader.js + +(function() { +enyo = window.enyo || {}, enyo.pathResolverFactory = function() { +this.paths = {}; +}, enyo.pathResolverFactory.prototype = { +addPath: function(e, t) { +return this.paths[e] = t; +}, +addPaths: function(e) { +if (e) for (var t in e) this.addPath(t, e[t]); +}, +includeTrailingSlash: function(e) { +return e && e.slice(-1) !== "/" ? e + "/" : e; +}, +rewritePattern: /\$([^\/\\]*)(\/)?/g, +rewrite: function(e) { +var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { +return t = !0, n(r[i]) || ""; +}, s = e; +do t = !1, s = s.replace(this.rewritePattern, i); while (t); +return s; +} +}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { +this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; +}, enyo.loaderFactory.prototype = { +verbose: !1, +loadScript: function(e) { +this.machine.script(e); +}, +loadSheet: function(e) { +this.machine.sheet(e); +}, +loadPackage: function(e) { +this.machine.script(e); +}, +report: function() {}, +load: function() { +this.more({ +index: 0, +depends: arguments || [] +}); +}, +more: function(e) { +if (e && this.continueBlock(e)) return; +var t = this.stack.pop(); +t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); +}, +finish: function() { +this.packageFolder = "", this.verbose && console.log("-------------- fini"); +for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); +}, +continueBlock: function(e) { +while (e.index < e.depends.length) { +var t = e.depends[e.index++]; +if (t) if (typeof t == "string") { +if (this.require(t, e)) return !0; +} else this.pathResolver.addPaths(t); +} +}, +require: function(e, t) { +var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); +n = r + n; +if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { +if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; +this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); +} +}, +getPathPrefix: function(e) { +var t = e.slice(0, 1); +return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; +}, +requireStylesheet: function(e) { +this.sheets.push(e), this.loadSheet(e); +}, +requireScript: function(e, t) { +this.modules.push({ +packageName: this.packageName, +rawPath: e, +path: t +}), this.loadScript(t); +}, +decodePackagePath: function(e) { +var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; +if (s.length) { +var a = s.pop() || s.pop() || ""; +a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; +for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { +s.splice(o, 1); +break; +} +n = s.join("/"); +for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { +s = s.slice(o + 1); +break; +} +for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); +t = s.join("-"); +} +return { +alias: t, +target: n, +folder: r, +manifest: i +}; +}, +aliasPackage: function(e) { +var t = this.decodePackagePath(e); +this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ +name: t.alias, +folder: t.folder +})), this.packageFolder = t.folder; +}, +requirePackage: function(e, t) { +t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); +} +}; +})(); + +// boot.js + +enyo.execUnsafeLocalFunction = function(e) { +typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); +}, enyo.machine = { +sheet: function(e) { +var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; +r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); +var i; +enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { +document.write(''); +}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { +less.refresh(!0); +})); +}, +script: function(e, t, n) { +if (!enyo.runtimeLoading) document.write(' + + + + + + diff --git a/assets/Diary.png b/assets/Diary.png new file mode 100644 index 0000000000000000000000000000000000000000..ae0450d94d017a53e5e603ec8d97dfc1312ee974 GIT binary patch literal 7666 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 literal 0 HcmV?d00001 diff --git a/assets/check.png b/assets/check.png new file mode 100644 index 0000000000000000000000000000000000000000..f0f1bfecf26d4470b0f3f40fc7db17330e8d8748 GIT binary patch literal 13502 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 z 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 Z0%!8y9*oUfC7+B17ACgF)e!gS{{fhy`m_K5 literal 0 HcmV?d00001 diff --git a/assets/month.png b/assets/month.png new file mode 100644 index 0000000000000000000000000000000000000000..1fd74b23bbecfd96982af5629ee09c3829a37b4c GIT binary patch literal 26463 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

    U>J|3KdE|4E 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 c=NIH;H(z*VHaFBNk^w($b$zumRjW7u1t * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + /* float when not stretched */ + float: left; + clear: both; +} + +/* non-floating when stretched */ +.enyo-fittable-rows-layout.enyo-stretch > * { + float: none; + clear: none; +} + +/* setting to enforce margin collapsing */ +/* NOTE: rows cannot have margin left/right */ +.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { + float: left; + clear: both; + width: 100%; + /* note: harsh resets */ + margin-left: 0 !important; + margin-right: 0 !important; +} + +.enyo-fittable-columns-layout { + position: relative; + text-align: left; + white-space: nowrap; +} + +.enyo-fittable-columns-layout.enyo-center { + text-align: center; +} + +.enyo-fittable-columns-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + vertical-align: top; + display: inline-block; + white-space: normal; +} + +.enyo-fittable-columns-layout.enyo-tool-decorator > * { + vertical-align: middle; +} + +/* repair clobbered white-space setting for pre, code */ +.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { + white-space: pre; +} + +.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { + white-space: nowrap; +} + +/* NOTE: columns cannot have margin top/bottom */ +.enyo-fittable-columns-layout.enyo-stretch > * { + height: 100%; + /* note: harsh resets */ + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/List.css */ + +.enyo-list { + position: relative; +} + +.enyo-list-port { + overflow: hidden; + position: relative; + height: 1000000px; +} + +.enyo-list-page, .enyo-list-holdingarea { + position: absolute; + left: 0; + right: 0; +} + +.enyo-list-holdingarea { + top: -10000px; +} + +.enyo-pinned-list-placeholder { + border: 1px solid red; + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-pinned-list-placeholder button { + width: 100px; height: 100%; + position: absolute; + top: 0; right: 0; +} + +.enyo-list-reorder-container { + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-animatedTopAndLeft { + -webkit-transition: top 0.1s linear, left 0.1s linear; + -moz-transition: top 0.1s linear, left 0.1s linear; + -o-transition: top 0.1s linear, left 0.1s linear; + transition: top 0.1s linear, left 0.1s linear; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/PulldownList.css */ + +.enyo-list-pulldown { + position: absolute; + bottom: 100%; + left: 0; + right: 0; +} + +.enyo-puller { + position: relative; + height: 50px; + font-size: 22px; + color: #444; + padding: 20px 0 0px 34px; +} + +.enyo-puller-text { + position: absolute; + left: 80px; + top: 22px; +} + +.enyo-puller-arrow { + position: relative; + background: #444; + width: 7px; + height: 28px; + transition: transform 0.3s; + -webkit-transition: -webkit-transform 0.3s; + -moz-transition: -moz-transform 0.3s; + -o-transition: -o-transform 0.3s; + -ms-transition: -ms-transform 0.3s; +} + +.enyo-puller-arrow:after { + content: " "; + height: 0; + width: 0; + position: absolute; + border: 10px solid transparent; + border-bottom-color: #444; + bottom: 100%; + left: 50%; + margin-left: -10px; +} + +.enyo-puller-arrow-up { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); +} + +.enyo-puller-arrow-down { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); + -ms-transform: rotate(180deg); +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/arrangers/Arranger.css */ + +.enyo-arranger { + position: relative; + overflow: hidden; +} + +.enyo-arranger.enyo-fit { + position: absolute; +} + +.enyo-arranger > * { + position: absolute; + left: 0; + top: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.enyo-arranger-fit > * { + /* override any width/height set on panels */ + width: 100% !important; + height: 100% !important; + min-width: 0 !important; + min-height: 0 !important; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/Panels.css */ + +.enyo-panels { +} + +.enyo-panels-fit-narrow { +} + +@media all and (max-width: 800px) { + .enyo-panels-fit-narrow > * { + min-width: 100%; + max-width: 100%; + } +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/tree/source/Node.css */ + +.enyo-node { + cursor: default; + padding: 4px; +} + +.enyo-node img { + vertical-align: middle; + padding-right: 6px; +} + +.enyo-node-box { + overflow: hidden; +} + +.enyo-node-client { + position: relative; +} + +.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { + -ms-transition-property: height, top; + -ms-transition-duration: 0.2s, 0.2s; + -moz-transition-property: height, top; + -moz-transition-duration: 0.2s, 0.2s; + -o-transition-property: height, top; + -o-transition-duration: 0.2s, 0.2s; + -webkit-transition-property: height, top; + -webkit-transition-duration: 0.2s, 0.2s; + transition-property: height, top; + transition-duration: 0.2s, 0.2s; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/imageview/source/ImageViewPin.css */ + + +.pinDebug { + background:yellow; + border:1px solid yellow; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/css/onyx.less */ + +/* Onyx default parameters defined here */ +/* Fonts */ +/* ---------------------------------------*/ +/* Text Colors */ +/* ---------------------------------------*/ +/* Background Colors */ +/* ---------------------------------------*/ +/* Border Radius */ +/* ---------------------------------------*/ +/* Padding */ +/* ---------------------------------------*/ +/* Icon Sizes */ +/* ---------------------------------------*/ +/* Disabled Opacity */ +/* ---------------------------------------*/ +/* Gradient Overlays */ +/* ---------------------------------------*/ +/* Images */ +/* ---------------------------------------*/ +/* Onyx rules defined here */ +/* onyx-classes.less - combined CSS (less) files for all released Onyx controls + into single onyx.less file to avoid IE bug that allows + a maximum of 31 style sheets to be loaded before silently failing */ +.onyx { + color: #333333; + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; + font-size: 20px; + cursor: default; + background-color: #eaeaea; + /* remove automatic tap highlight color */ + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +/* prevent IE from inheriting line-height for these elements */ +.onyx button, +.onyx label, +.onyx input { + line-height: normal; +} +.onyx-selected { + background-color: #c4e3fe; +} +/* LESS pre-calculations */ +/* Individual Widget CSS */ +/* Icon.css */ +.onyx-icon, +.onyx-icon-toggle { + width: 32px; + height: 32px; + background-repeat: no-repeat; + display: inline-block; + vertical-align: middle; +} +.onyx-icon.onyx-icon-button.active, +.onyx-icon.onyx-icon-button.pressed, +.onyx-icon.onyx-icon-button:active:hover, +.onyx-icon-toggle.active { + background-position: 0 -32px; +} +.onyx-icon.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-icon.disabled:active:hover { + background-position: 0 0px; +} +/* Button.css */ +.onyx-button { + outline: 0; + color: #292929; + font-size: 16px; + text-align: center; + white-space: nowrap; + margin: 0; + padding: 6px 18px; + overflow: hidden; + border-radius: 3px; + /* for IE8 */ + + border: 1px solid #707070; + border: 1px solid rgba(15, 15, 15, 0.2); + /* + The border and the gradient interact in a strange way that + causes the bottom-border (top if the gradient is aligned top) + to be lighter than other borders. + We can fix it by using the darker bottom border below, but + then there are a few rogue pixels that end up very dark. + */ + + /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ + + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); + background: #e1e1e1 url(../lib/onyx/images/gradient.png) repeat-x bottom; + background-size: contain; + /**/ + + text-overflow: ellipsis; + /* the following cause arcane problems on IE */ + + /* + min-width: 14px; + min-height: 20px; + */ + +} +/* + IE8 can't handle these selectors in tandem: + .onyx-button.active, .onyx-button:active:not([disabled]) { + + the effect is as if .onyx-button.active doesn't exist +*/ +.onyx-button.active, +.onyx-button.pressed { + background-image: url(../lib/onyx/images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button:active:hover:not([disabled]) { + background-image: url(../lib/onyx/images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button[disabled] { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-button > img { + padding: 0px 3px; +} +/* Remove the focused inner-border style in Firefox (Windows) */ +.onyx-button::-moz-focus-inner { + border: 0; +} +/* Checkbox.css */ +.onyx-checkbox { + cursor: pointer; + height: 32px; + width: 32px; + background: url(../lib/onyx/images/checkbox.png) no-repeat; + /* reset for ? */ + + margin: 0px; + /* these entries cause toggle-button and checkbox to line up properly*/ + + display: inline-block; + vertical-align: middle; +} +.onyx-checkbox[checked] { + background-position: 0px -32px; +} +.onyx-checkbox[disabled] { + opacity: 0.4; +} +/* Grabber.css */ +.onyx-grabber { + background: url(../lib/onyx/images/grabbutton.png) no-repeat center; + width: 23px; + height: 27px; +} +/* Popup.css */ +.onyx-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; +} +.onyx-popup-decorator { + position: relative; +} +/* Groupbox.css */ +.onyx-groupbox > * { + display: block; + /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ + + border-color: #aaaaaa; + border-style: solid; + border-width: 0 1px 1px 1px; + /*padding: 10px;*/ + + /* reset styles that make 'item' look bad if they happen to be there */ + + border-radius: 0; + margin: 0; + font-size: 16px; +} +.onyx-groupbox > *:first-child { + border-top-color: #aaaaaa; + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > *:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > *:first-child:last-child { + border-radius: 4px; +} +.onyx-groupbox-header { + padding: 2px 10px; + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; + /**/ + + background-color: #4c4c4c; + border: none; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 10px; +} +.onyx-groupbox .onyx-input-decorator { + display: block; +} +.onyx-groupbox > .onyx-input-decorator { + border-color: #aaaaaa; + border-width: 0 1px 1px 1px; + border-radius: 0; +} +.onyx-groupbox > .onyx-input-decorator:first-child { + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > .onyx-input-decorator:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > .onyx-input-decorator:first-child:last-child { + border-radius: 4px; +} +/* Input.css */ +.onyx-input-decorator { + padding: 6px 8px 10px 8px; + border-radius: 3px; + border: 1px solid; + border-color: rgba(0, 0, 0, 0.1); + margin: 0; +} +.onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + border-color: rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-input-decorator.onyx-disabled { + /* FIXME: needed to color a disabled input placeholder. */ + + /*-webkit-text-fill-color: #888;*/ + + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-input-decorator > input { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > input { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > input { + cursor: default; +} +/* Menu.css */ +.onyx-menu, +.onyx.onyx-menu { + min-width: 160px; + top: 100%; + left: 0; + margin-top: 2px; + padding: 3px 0; + border-radius: 3px; +} +.onyx-menu.onyx-menu-up { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 2px; +} +.onyx-toolbar .onyx-menu { + margin-top: 11px; + border-radius: 0 0 3px 3px; +} +.onyx-toolbar .onyx-menu.onyx-menu-up { + margin-top: 0; + margin-bottom: 10px; + border-radius: 3px 3px 0 0; +} +.onyx-menu-item { + display: block; + padding: 10px; +} +.onyx-menu-item:hover { + background: #284152; +} +.onyx-menu-divider, +.onyx-menu-divider:hover { + margin: 6px 0; + padding: 0; + border-bottom: 1px solid #aaa; +} +.onyx-menu-label { + cursor: default; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-menu-label:hover { + background: none; +} +/* customize a toolbar to support menus */ +.onyx-menu-toolbar, +.onyx-toolbar.onyx-menu-toolbar { + position: relative; + z-index: 10; + overflow: visible; +} +/* Picker.css */ +.onyx-picker-decorator .onyx-button { + padding: 10px 18px; +} +.onyx-picker { + top: 0; + margin-top: -3px; + min-width: 0; + width: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + color: black; + background: #e1e1e1; +} +.onyx-picker.onyx-menu-up { + top: auto; + bottom: 0; + margin-top: 3px; + margin-bottom: -3px; +} +.onyx-picker .onyx-menu-item { + text-align: center; +} +.onyx-picker .onyx-menu-item:hover { + background-color: transparent; +} +.onyx-picker .onyx-menu-item.selected, +.onyx-picker .onyx-menu-item.active, +.onyx-picker .onyx-menu-item:active:hover { + border-top: 1px solid rgba(0, 0, 0, 0.1); + background-color: #cde7fe; + box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); +} +.onyx-picker .onyx-menu-item { + border-top: 1px solid rgba(255, 255, 255, 0.5); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, +.onyx-flyweight-picker :first-child > .onyx-menu-item { + border-top: none; +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, +.onyx-flyweight-picker :last-child > .onyx-menu-item { + border-bottom: none; +} +/* TextArea.css */ +.onyx-input-decorator > textarea { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* Remove scrollbars and resize handle */ + + resize: none; + overflow: auto; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > textarea { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > textarea { + cursor: default; +} +.onyx-textarea { + /* need >=50px for scrollbar to be usable on mac */ + + min-height: 50px; +} +/* RichText.css */ +.onyx-input-decorator > .onyx-richtext { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + min-height: 20px; + min-width: 100px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > .onyx-richtext { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > .onyx-richtext { + cursor: default; +} +/* RadioButton.css */ +.onyx-radiobutton { + padding: 8px 12px; + margin: 0; + outline: 0; + font-size: 16px; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + text-align: center; + /**/ + + background: #e7e7e7 url(../lib/onyx/images/gradient.png) repeat-x bottom; + /* IE8 */ + + border: 1px solid #333333; + border: 1px solid rgba(15, 15, 15, 0.2); + /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ + + border-right-color: rgba(0, 0, 0, 0); + box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); +} +.onyx-radiobutton:first-child { + border-radius: 3px 0 0 3px; +} +.onyx-radiobutton:last-child { + border-radius: 0px 3px 3px 0px; + /* IE8 */ + + border-right: 1px solid #333333; + border-right: 1px solid rgba(15, 15, 15, 0.2); +} +.onyx-radiobutton.active { + color: #ffffff; + background: #0091f2 url(../lib/onyx/images/gradient-invert.png) repeat-x top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); +} +/* Scrim.css */ +.onyx-scrim { + z-index: 1; + /* + note: by using pointer-events we allow tapping on scrim + while it is fading out; however, this requires any showing classes + to set pointer events to auto or scrim will not function as expected. + */ + + pointer-events: none; +} +.onyx-scrim.onyx-scrim-translucent { + pointer-events: auto; + background-color: #000000; + opacity: 0.65; + filter: alpha(opacity=65); +} +.onyx-scrim.onyx-scrim-transparent { + pointer-events: auto; + background: transparent; +} +/* TabButton.css */ +.onyx-radiobutton.onyx-tabbutton { + padding: 8px 34px; + font-size: 20px; + border-radius: 0px; +} +/* ToggleButton.css */ +.onyx-toggle-button { + display: inline-block; + height: 32px; + line-height: 32px; + min-width: 64px; + vertical-align: middle; + text-align: center; + /* */ + + border-radius: 3px; + box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); + background: #8bba3d url(../lib/onyx/images/gradient-invert.png) repeat-x bottom; + background-size: auto 100%; + /* label */ + + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; +} +.onyx-toggle-button.off { + background-color: #b1b1b1 !important; +} +.onyx-toggle-button-knob { + display: inline-block; + width: 30px; + height: 30px; + margin: 1px; + border-radius: 3px; + background: #f6f6f6 url(../lib/onyx/images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-toggle-button .onyx-toggle-button-knob { + box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: right; +} +.onyx-toggle-button.off .onyx-toggle-button-knob { + box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: left; +} +.onyx-toggle-button.disabled, +.onyx-icon-button.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-toggle-content { + min-width: 32px; + padding: 0 6px; +} +.onyx-toggle-content.empty { + padding: 0; +} +.onyx-toggle-content.off { + float: right; +} +.onyx-toggle-content.on { + float: left; +} +/* Toolbar.css */ +.onyx-toolbar { + /* + line-height is unreliable for centering, instead + use vertical-align: middle to align + elements along a common centerline and use + padding to fill out the space. + */ + + padding: 9px 8px 10px 8px; + border: 1px solid #3A3A3A; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; + background-size: contain; + color: #ffffff; + /**/ + + white-space: nowrap; + overflow-y: visible; + font-size: 20px; +} +.onyx-toolbar-inline > *, +.enyo-fittable-columns-layout.onyx-toolbar-inline > * { + display: inline-block; + vertical-align: middle; + margin: 4px 6px 5px; + box-sizing: border-box; +} +.onyx-toolbar .onyx-icon-button { + margin: 3px 2px 1px; +} +.onyx-toolbar .onyx-button { + color: #f2f2f2; + background-color: #555656; + border-color: rgba(15, 15, 15, 0.5); + margin-top: 0; + margin-bottom: 0; + height: 36px; +} +.onyx-toolbar .onyx-input-decorator { + margin: 1px 3px; + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); + padding: 0px 6px 5px 6px; +} +.onyx-toolbar .onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-toolbar .onyx-input-decorator .onyx-input { + color: #e5e5e5; + font-size: 14px; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus { + color: #000000; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { + color: #dddddd; +} +/* Tooltip.css */ +.onyx-tooltip { + z-index: 20; + left: 0; + padding: 4px 6px; + margin-top: 4px; + margin-left: -6px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + color: #ffffff; + background: #216593 url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; + border-radius: 3px; + white-space: nowrap; +} +/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ +.onyx-tooltip.right-arrow { + left: 30px; +} +/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ +.onyx-tooltip::before { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + left: 16px; +} +.onyx-tooltip::after { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + margin-left: -12px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ +.onyx-tooltip.below { + top: 100%; +} +.onyx-tooltip.below.right-arrow::after { + border-bottom: 6px solid #1D587F; + top: -6px; +} +.onyx-tooltip.below.left-arrow::before { + border-bottom: 6px solid #1D587F; + top: -6px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ +.onyx-tooltip.above { + top: -100%; +} +.onyx-tooltip.above.right-arrow::after { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +.onyx-tooltip.above.left-arrow::before { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +/* ProgressBar.css */ +.onyx-progress-bar { + margin: 8px; + height: 8px; + border: 1px solid rgba(15, 15, 15, 0.2); + border-radius: 3px; + background: #b8b8b8 url(../lib/onyx/images/gradient-invert.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar { + height: 100%; + border-radius: 3px; + background: #58abef url(../lib/onyx/images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar.striped { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.onyx-progress-bar-bar.striped.animated { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +/* ProgressButton.css */ +.onyx-progress-button { + position: relative; + height: 36px; + line-height: 36px; + color: #f1f1f1; + font-size: 16px; + text-overflow: ellipsis; +} +.onyx-progress-button-bar { + height: 36px; +} +.onyx-progress-button-icon { + display: inline-block; + position: absolute; + top: 2px; + right: 0; +} +.onyx-progress-button-client { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 36px; + margin-left: 8px; +} +.onyx-progress-button-client > * { + display: inline-block; +} +/* Slider.css */ +.onyx-slider { + position: relative; + margin: 8px 20px; +} +.onyx-slider-taparea { + position: absolute; + top: -11px; + height: 28px; + width: 100%; +} +.onyx-slider-knob { + position: relative; + height: 40px; + width: 40px; + background: url(../lib/onyx/images/slider-handle.png) left top no-repeat; + margin: -23px -20px; +} +.onyx-slider-knob.active, +.onyx-slider-knob.pressed, +.onyx-slider-knob:active:hover { + background-position: 0 -40px; +} +/* RangeSlider.css */ +.onyx-range-slider-knob { + top: -17px; +} +.onyx-range-slider-label { + position: relative; + top: -18px; + text-align: center; + white-space: nowrap; +} +/* Item.css */ +.onyx-item { + padding: 14px; +} +.onyx-highlight, +.onyx-highlight.onyx-swipeable-item-content { + background-color: #dedfdf; +} +.enyo-selected, +.enyo-selected.onyx-swipeable-item-content { + background-color: #c4e3fe; +} +.onyx-item.onyx-swipeable-item { + overflow: hidden; + padding: 0; +} +.onyx-swipeable-item-content { + background-color: #eaeaea; + box-sizing: border-box; + padding: 18px 6px; + min-height: 40px; +} +/* Spinner.css */ +.onyx-spinner { + width: 59px; + height: 58px; + display: inline-block; + background: url(../lib/onyx/images/spinner-dark.gif) no-repeat 0 0; +} +.onyx-spinner.onyx-light { + background: url(../lib/onyx/images/spinner-light.gif) no-repeat 0 0; +} +/* MoreToolbar.css */ +.onyx-more-toolbar { + overflow: visible; + position: relative; + z-index: 10; +} +.onyx-more-toolbar.active { + z-index: 11; +} +.onyx-more-menu { + left: auto; + right: 0px; + min-width: 0; +} +.onyx-more-toolbar .onyx-more-menu > * { + float: right; + clear: both; + margin: 5px; + margin-top: 5px; + margin-bottom: 5px; +} +.onyx-more-button { + background-image: url(../lib/onyx/images/more.png); + width: 32px; + height: 32px; +} +/* DatePicker.css */ +.onyx-datepicker-month { + min-width: 75px; +} +.onyx-datepicker-day { + min-width: 60px; +} +.onyx-datepicker-year { + min-width: 70px; +} +/* TimePicker.css */ +.onyx-timepicker-hour { + min-width: 60px; +} +.onyx-timepicker-minute { + min-width: 60px; +} +.onyx-timepicker-ampm { + min-width: 60px; +} +/* ButtonColors.css */ +.onyx-button.onyx-blue { + background-color: #35A8EE; + color: #F2F2F2; +} +.onyx-button.onyx-affirmative { + background-color: #91BA07; + color: #F2F2F2; +} +.onyx-button.onyx-negative { + background-color: #C51616; + color: #F2F2F2; +} +.onyx-button.onyx-dark { + background-color: #555656; + color: #F2F2F2; +} +.onyx-button.onyx-light { + background-color: #cacaca; + color: #2F2F2F; +} +/* ContextualPopup.css */ +.onyx-contextual-popup-title { + font-weight: bold; + padding: 24px 32px 0px; +} +.onyx-contextual-popup-scroller { + padding: 24px 32px; +} +.onyx-contextual-popup-action-buttons { + display: inline-block; + width: 100%; + text-align: center; +} +.onyx-contextual-popup-action-button { + margin-left: 5px; + margin-right: 5px; +} +.onyx-contextual-popup, +.onyx.onyx-contextual-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c; +} +/*setup the nub*/ +.onyx-contextual-popup::after { + content: ''; + position: absolute; + top: -10px; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; +} +/*for popups above activator*/ +.onyx-contextual-popup.vertical.above { + top: auto; + margin-top: -10px; + bottom: 100%; + margin-bottom: 10px; +} +/*for popups below activator*/ +.onyx-contextual-popup.vertical.below { + margin-top: 10px; +} +/*for popups on the left of the activator*/ +.onyx-contextual-popup.right.horizontal { + margin-left: -11px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.left.horizontal { + margin-left: 10px; +} +/*nub positioning*/ +/*horizontally centered nub*/ +.onyx-contextual-popup.vertical::after { + position: absolute; + left: 45%; + border-bottom: 10px solid #4c4c4c; + border-top: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +/*nub near horizontal left*/ +.onyx-contextual-popup.vertical.right::after { + left: 0%; + margin-left: 20px; +} +/*nub near horizontal right*/ +.onyx-contextual-popup.vertical.left::after { + left: 100%; + margin-left: -55px; +} +/*downward facing nub*/ +.onyx-contextual-popup.vertical.above::after { + top: 100%; + border-top: 10px solid #4c4c4c; + border-bottom: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right::after { + top: 0%; + margin-top: -10px; + border-bottom: 10px solid #4c4c4c; + border-left: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.left::after { + top: 0%; + margin-top: -10px; + border-right: 10px solid transparent; +} +/*nub positioning for left/right popups*/ +/*vertically centered nub for popups on left of activator*/ +.onyx-contextual-popup.right::after { + left: 100%; + top: 47%; + margin-right: 20px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on left of activator*/ +.onyx-contextual-popup.right.high::after { + top: 35px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on left of activator*/ +.onyx-contextual-popup.right.low::after { + top: 100%; + margin-top: -55px; + border-left: 10px solid #4C4C4C; +} +/*vertically centered nub for popups on right of activator*/ +.onyx-contextual-popup.left::after { + left: 0%; + margin-left: -20px; + top: 45%; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on right of activator*/ +.onyx-contextual-popup.left.high::after { + top: 35px; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on right of activator*/ +.onyx-contextual-popup.left.low::after { + top: 100%; + margin-top: -55px; + border-right: 10px solid #4C4C4C; +} +/*corners*/ +/*vertical top corners*/ +/*for popups on the left of the activator*/ +.onyx-contextual-popup.vertical.right.corner { + margin-left: 0px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.vertical.left.corner { + margin-left: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.vertical.below.right.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner::after { + top: 0%; + left: 100%; + margin-top: -10px; + margin-left: -19px; + border-right: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right.corner::after { + top: 0%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +/*vertical bottom corners*/ +.onyx-contextual-popup.left.above.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.right.above.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.vertical.left.above.corner::after { + top: 100%; + margin-left: -19px; + border-right: 10px solid #4C4C4C; + border-bottom: 10px solid transparent; + border-top: none; +} +.onyx-contextual-popup.vertical.right.above.corner::after { + top: 100%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-bottom: 10px solid transparent; + border-top: none; +} +/*horizontal bottom corners*/ +.onyx-contextual-popup.left.low.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.right.low.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.left.low.corner::after { + top: 100%; + left: 0%; + margin-top: -19px; + margin-left: -12px; + border-bottom: 10px solid #4c4c4c; + border-right: 10px solid #4c4c4c; +} +.onyx-contextual-popup.right.low.corner::after { + top: 100%; + left: 100%; + margin-top: -19px; + border-bottom: 10px solid#4c4c4c; + border-left: none; +} +/*horizontal top corners*/ +.onyx-contextual-popup.left.high.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.right.high.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.left.high.corner::after { + top: 0%; + left: 0%; + margin-top: -1px; + margin-left: -12px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +.onyx-contextual-popup.right.high.corner::after { + top: 0%; + left: 100%; + margin-top: -1px; + margin-left: -9px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +/* some default colors */ +.onyx-dark { + background-color: #555656; +} +.onyx-light { + background-color: #cacaca; +} +.onyx-green { + background-color: #91BA07; +} +.onyx-red { + background-color: #C51616; +} +.onyx-blue { + background-color: #35A8EE; +} + + +/* source/App.css */ + +/* + Put anything you reference with "url(../source)" in ../assets/ + This way, you can minify your application, and just remove the "source" folder for production +*/ +.nice-padding { + padding: 15px; +} diff --git a/build/app.js b/build/app.js new file mode 100644 index 0000000..7a17c89 --- /dev/null +++ b/build/app.js @@ -0,0 +1,4447 @@ + +// minifier: path aliases + +enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/source/"}); + +// FittableLayout.js + +enyo.kind({ +name: "enyo.FittableLayout", +kind: "Layout", +calcFitIndex: function() { +for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; +}, +getFitControl: function() { +var e = this.container.children, t = e[this.fitIndex]; +return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; +}, +getLastControl: function() { +var e = this.container.children, t = e.length - 1, n = e[t]; +while ((n = e[t]) && !n.showing) t--; +return n; +}, +_reflow: function(e, t, n, r) { +this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); +var i = this.getFitControl(); +if (!i) return; +var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); +f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); +var l = i.getBounds(); +o = l[n] - (a && a[n] || 0); +var c = this.getLastControl(); +if (c) { +var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; +if (c != i) { +var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; +u = v - d; +} else u = h; +} +var m = s - (o + u); +i.applyStyle(e, m + "px"); +}, +reflow: function() { +this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); +} +}), enyo.kind({ +name: "enyo.FittableColumnsLayout", +kind: "FittableLayout", +orient: "h", +layoutClass: "enyo-fittable-columns-layout" +}), enyo.kind({ +name: "enyo.FittableRowsLayout", +kind: "FittableLayout", +layoutClass: "enyo-fittable-rows-layout", +orient: "v" +}); + +// FittableRows.js + +enyo.kind({ +name: "enyo.FittableRows", +layoutKind: "FittableRowsLayout", +noStretch: !1 +}); + +// FittableColumns.js + +enyo.kind({ +name: "enyo.FittableColumns", +layoutKind: "FittableColumnsLayout", +noStretch: !1 +}); + +// FlyweightRepeater.js + +enyo.kind({ +name: "enyo.FlyweightRepeater", +published: { +count: 0, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +clientClasses: "", +clientStyle: "", +rowOffset: 0 +}, +events: { +onSetupItem: "", +onRenderRow: "" +}, +bottomUp: !1, +components: [ { +kind: "Selection", +onSelect: "selectDeselect", +onDeselect: "selectDeselect" +}, { +name: "client" +} ], +create: function() { +this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); +}, +noSelectChanged: function() { +this.noSelect && this.$.selection.clear(); +}, +multiSelectChanged: function() { +this.$.selection.setMulti(this.multiSelect); +}, +clientClassesChanged: function() { +this.$.client.setClasses(this.clientClasses); +}, +clientStyleChanged: function() { +this.$.client.setStyle(this.clientStyle); +}, +setupItem: function(e) { +this.doSetupItem({ +index: e, +selected: this.isSelected(e) +}); +}, +generateChildHtml: function() { +var e = ""; +this.index = null; +for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); +return e; +}, +previewDomEvent: function(e) { +var t = this.index = this.rowForEvent(e); +e.rowIndex = e.index = t, e.flyweight = this; +}, +decorateEvent: function(e, t, n) { +var r = t && t.index != null ? t.index : this.index; +t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); +}, +tap: function(e, t) { +if (this.noSelect || t.index === -1) return; +this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); +}, +selectDeselect: function(e, t) { +this.renderRow(t.key); +}, +getSelection: function() { +return this.$.selection; +}, +isSelected: function(e) { +return this.getSelection().isSelected(e); +}, +renderRow: function(e) { +if (e < this.rowOffset || e >= this.count + this.rowOffset) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ +rowIndex: e +})); +}, +fetchRowNode: function(e) { +if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); +}, +rowForEvent: function(e) { +if (!this.hasNode()) return -1; +var t = e.target; +while (t && t !== this.node) { +var n = t.getAttribute && t.getAttribute("data-enyo-index"); +if (n !== null) return Number(n); +t = t.parentNode; +} +return -1; +}, +prepareRow: function(e) { +if (e < 0 || e >= this.count) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +enyo.FlyweightRepeater.claimNode(this.$.client, t); +}, +lockRow: function() { +this.$.client.teardownChildren(); +}, +performOnRow: function(e, t, n) { +if (e < 0 || e >= this.count) return; +t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); +}, +statics: { +claimNode: function(e, t) { +var n; +t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); +for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); +} +} +}); + +// List.js + +enyo.kind({ +name: "enyo.List", +kind: "Scroller", +classes: "enyo-list", +published: { +count: 0, +rowsPerPage: 50, +bottomUp: !1, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +fixedHeight: !1, +reorderable: !1, +centerReorderContainer: !0, +reorderComponents: [], +pinnedReorderComponents: [], +swipeableComponents: [], +enableSwipe: !1, +persistSwipeableItem: !1 +}, +events: { +onSetupItem: "", +onSetupReorderComponents: "", +onSetupPinnedReorderComponents: "", +onReorder: "", +onSetupSwipeItem: "", +onSwipeDrag: "", +onSwipe: "", +onSwipeComplete: "" +}, +handlers: { +onAnimateFinish: "animateFinish", +onRenderRow: "rowRendered", +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onup: "up", +onholdpulse: "holdpulse" +}, +rowHeight: 0, +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0;" +} ] +} ], +reorderHoldTimeMS: 600, +draggingRowIndex: -1, +draggingRowNode: null, +placeholderRowIndex: -1, +dragToScrollThreshold: .1, +prevScrollTop: 0, +autoScrollTimeoutMS: 20, +autoScrollTimeout: null, +autoscrollPageY: 0, +pinnedReorderMode: !1, +initialPinPosition: -1, +itemMoved: !1, +currentPageNumber: -1, +completeReorderTimeout: null, +swipeIndex: null, +swipeDirection: null, +persistentItemVisible: !1, +persistentItemOrigin: null, +swipeComplete: !1, +completeSwipeTimeout: null, +completeSwipeDelayMS: 500, +normalSwipeSpeedMS: 200, +fastSwipeSpeedMS: 100, +percentageDraggedThreshold: .2, +importProps: function(e) { +e && e.reorderable && (this.touch = !0), this.inherited(arguments); +}, +create: function() { +this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); +}, +initComponents: function() { +this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); +}, +createReorderTools: function() { +this.createComponent({ +name: "reorderContainer", +classes: "enyo-list-reorder-container", +ondown: "sendToStrategy", +ondrag: "sendToStrategy", +ondragstart: "sendToStrategy", +ondragfinish: "sendToStrategy", +onflick: "sendToStrategy" +}); +}, +createStrategy: function() { +this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); +}, +createSwipeableComponents: function() { +for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { +owner: this.owner +}); +}, +rendered: function() { +this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); +}, +resizeHandler: function() { +this.inherited(arguments), this.refresh(); +}, +bottomUpChanged: function() { +this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); +}, +noSelectChanged: function() { +this.$.generator.setNoSelect(this.noSelect); +}, +multiSelectChanged: function() { +this.$.generator.setMultiSelect(this.multiSelect); +}, +toggleSelectedChanged: function() { +this.$.generator.setToggleSelected(this.toggleSelected); +}, +countChanged: function() { +this.hasNode() && this.updateMetrics(); +}, +sendToStrategy: function(e, t) { +this.$.strategy.dispatchEvent("on" + t.type, t, e); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +holdpulse: function(e, t) { +if (!this.getReorderable() || this.isReordering()) return; +if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; +}, +dragstart: function(e, t) { +if (this.isReordering()) return !0; +if (this.isSwipeable()) return this.swipeDragStart(e, t); +}, +drag: function(e, t) { +if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; +if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; +}, +dragfinish: function(e, t) { +this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); +}, +up: function(e, t) { +this.isReordering() && this.finishReordering(e, t); +}, +generatePage: function(e, t) { +this.page = e; +var n = this.rowsPerPage * this.page; +this.$.generator.setRowOffset(n); +var r = Math.min(this.count - n, this.rowsPerPage); +this.$.generator.setCount(r); +var i = this.$.generator.generateChildHtml(); +t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); +var s = t.getBounds().height; +!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); +if (!this.fixedHeight) { +var o = this.getPageHeight(e); +this.pageHeights[e] = s, this.portSize += s - o; +} +}, +pageForRow: function(e) { +return Math.floor(e / this.rowsPerPage); +}, +preserveDraggingRowNode: function(e) { +this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); +}, +update: function(e) { +var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; +this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); +}, +getPageRowHeights: function(e) { +var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); +for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { +height: s.height, +width: s.width +}); +return t; +}, +updateRowBounds: function(e) { +this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); +}, +updateRowBoundsAtIndex: function(e, t, n) { +var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); +t[e].height = i.height, t[e].width = i.width; +}, +updateForPosition: function(e) { +this.update(this.calcPos(e)); +}, +calcPos: function(e) { +return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; +}, +adjustBottomPage: function() { +var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; +this.positionPage(e.pageNo, e); +}, +adjustPortSize: function() { +this.scrollerHeight = this.getBounds().height; +var e = Math.max(this.scrollerHeight, this.portSize); +this.$.port.applyStyle("height", e + "px"); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e); +t.applyStyle(this.pageBound, n + "px"); +}, +pageToPosition: function(e) { +var t = 0, n = e; +while (n > 0) n--, t += this.getPageHeight(n); +return t; +}, +positionToPageInfo: function(e) { +var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; +while (n >= 0) t++, r = this.getPageHeight(t), n -= r; +return t = Math.max(t, 0), { +no: t, +height: r, +pos: n + r, +startRow: t * this.rowsPerPage, +endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) +}; +}, +isPageInRange: function(e) { +return e == Math.max(0, Math.min(this.pageCount - 1, e)); +}, +getPageHeight: function(e) { +var t = this.pageHeights[e]; +if (!t) { +var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); +t = this.defaultPageHeight * (r / this.rowsPerPage); +} +return Math.max(1, t); +}, +invalidatePages: function() { +this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); +}, +invalidateMetrics: function() { +this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); +}, +scroll: function(e, t) { +var n = this.inherited(arguments), r = this.getScrollTop(); +return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); +}, +setScrollTop: function(e) { +this.update(e), this.inherited(arguments), this.twiddle(); +}, +getScrollPosition: function() { +return this.calcPos(this.getScrollTop()); +}, +setScrollPosition: function(e) { +this.setScrollTop(this.calcPos(e)); +}, +scrollToBottom: function() { +this.update(this.getScrollBounds().maxTop), this.inherited(arguments); +}, +scrollToRow: function(e) { +var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); +this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); +if (t == this.p0 || t == this.p1) { +var i = this.$.generator.fetchRowNode(e); +if (i) { +var s = i.offsetTop; +this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); +var o = this.getScrollPosition() + s; +this.setScrollPosition(o); +} +} +}, +scrollToStart: function() { +this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); +}, +scrollToEnd: function() { +this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); +}, +refresh: function() { +this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); +}, +reset: function() { +this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); +}, +getSelection: function() { +return this.$.generator.getSelection(); +}, +select: function(e, t) { +return this.getSelection().select(e, t); +}, +deselect: function(e) { +return this.getSelection().deselect(e); +}, +isSelected: function(e) { +return this.$.generator.isSelected(e); +}, +renderRow: function(e) { +this.$.generator.renderRow(e); +}, +rowRendered: function(e, t) { +this.updateRowBounds(t.rowIndex); +}, +prepareRow: function(e) { +this.$.generator.prepareRow(e); +}, +lockRow: function() { +this.$.generator.lockRow(); +}, +performOnRow: function(e, t, n) { +this.$.generator.performOnRow(e, t, n); +}, +animateFinish: function(e) { +return this.twiddle(), !0; +}, +twiddle: function() { +var e = this.getStrategy(); +enyo.call(e, "twiddle"); +}, +pageForPageNumber: function(e, t) { +return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; +}, +shouldStartReordering: function(e, t) { +return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; +}, +startReordering: function(e) { +this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); +}, +buildReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +styleReorderContainer: function(e) { +this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); +}, +appendNodeToReorderContainer: function(e) { +this.$.reorderContainer.createComponent({ +allowHtml: !0, +content: e.innerHTML +}).render(); +}, +centerReorderContainerOnPointer: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; +this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); +}, +positionReorderContainer: function(e, t) { +this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); +}, +setPositionReorderContainerTimeout: function() { +this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { +this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); +}), 100); +}, +clearPositionReorderContainerTimeout: function() { +this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); +}, +shouldDoReorderDrag: function() { +return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; +}, +reorderDrag: function(e) { +this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); +}, +updatePlaceholderPosition: function(e) { +var t = this.getRowIndexFromCoordinate(e); +t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); +}, +positionReorderNode: function(e) { +var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; +r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); +}, +checkForAutoScroll: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; +this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); +}, +stopAutoScrolling: function() { +this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); +}, +startAutoScrolling: function() { +this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); +}, +autoScroll: function() { +this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ +ddx: 0, +ddy: 0 +}), this.updatePlaceholderPosition(this.autoscrollPageY); +}, +movePlaceholderToIndex: function(e) { +var t, n; +if (e < 0) return; +e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); +var r = this.pageForRow(e); +r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; +}, +finishReordering: function(e, t) { +if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; +return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; +}, +moveReorderedContainerToDroppedPosition: function() { +var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); +this.positionReorderContainer(n, t); +}, +completeFinishReordering: function(e) { +this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); +if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { +this.beginPinnedReorder(e); +return; +} +this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); +}, +beginPinnedReorder: function(e) { +this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { +index: this.draggingRowIndex +})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; +}, +emptyAndHideReorderContainer: function() { +this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); +}, +buildPinnedReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +reorderRows: function(e) { +this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); +}, +makeReorderEvent: function(e) { +return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; +}, +positionReorderedNode: function() { +if (!this.removedInitialPage) { +var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); +e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; +if (this.currentPageNumber != this.initialPageNumber) { +var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); +this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); +} +} +}, +updateListIndices: function() { +if (this.shouldDoRefresh()) { +this.refresh(), this.correctPageHeights(); +return; +} +var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; +if (n === 1) { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); +for (i = t - 1, s = t; i >= e; i--) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); +} +r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); +} else { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); +for (i = e + 1, s = e; i <= t; i++) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); +} +} +}, +shouldDoRefresh: function() { +return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; +}, +getNodeStyle: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) return; +var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); +return { +h: r.height, +w: r.width, +left: n.left, +top: n.top +}; +}, +getRelativeOffset: function(e, t) { +var n = { +top: 0, +left: 0 +}; +if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); +return n; +}, +replaceNodeWithPlaceholder: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) { +enyo.log("No node - " + e); +return; +} +this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); +var n = this.pageForPageNumber(this.currentPageNumber); +n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); +}, +createPlaceholderNode: function(e) { +var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); +return t.style.height = n.height + "px", t.style.width = n.width + "px", t; +}, +removePlaceholderNode: function() { +this.removeNode(this.placeholderNode), this.placeholderNode = null; +}, +removeDraggingRowNode: function() { +this.draggingRowNode = null; +var e = this.$.holdingarea.hasNode(); +e.innerHTML = ""; +}, +removeNode: function(e) { +if (!e || !e.parentNode) return; +e.parentNode.removeChild(e); +}, +updatePageHeight: function(e) { +if (e < 0) return; +var t = this.pageForPageNumber(e, !0); +if (t) { +var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); +this.pageHeights[e] = r, this.portSize += r - n; +} +}, +updatePagePositions: function(e) { +this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); +}, +correctPageHeights: function() { +this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); +}, +hideNode: function(e) { +return e.style.display = "none", e; +}, +showNode: function(e) { +return e.style.display = "block", e; +}, +dropPinnedRow: function(e) { +this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); +return; +}, +cancelPinnedMode: function(e) { +this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); +}, +getRowIndexFromCoordinate: function(e) { +var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; +if (t < 0) return -1; +var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; +if (!r) return this.count; +var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; +for (var u = n.startRow; u <= n.endRow; ++u) { +if (u === this.placeholderRowIndex) { +o += s; +if (o >= i) return -1; +} +if (u !== this.draggingRowIndex) { +o += r[u].height; +if (o >= i) return u; +} +} +return u; +}, +getIndexPosition: function(e) { +return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); +}, +setItemPosition: function(e, t) { +var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; +e.addStyles(i); +}, +setItemBounds: function(e, t) { +var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; +e.addStyles(r); +}, +reorderScroll: function(e, t) { +this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); +}, +hideReorderingRow: function() { +var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); +e && (this.hiddenNode = this.hideNode(e)); +}, +isReordering: function() { +return this.draggingRowIndex > -1; +}, +isSwiping: function() { +return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; +}, +swipeDragStart: function(e, t) { +return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); +}, +swipeDrag: function(e, t) { +return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; +}, +swipeDragFinish: function(e, t) { +if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { +if (!this.isSwiping()) return !1; +var n = this.calcPercentageDragged(this.draggedXDistance); +n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); +} +return this.preventDragPropagation; +}, +isSwipeable: function() { +return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; +}, +positionSwipeableContainer: function(e, t) { +var n = this.$.generator.fetchRowNode(e); +if (!n) return; +var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; +this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); +}, +calcNewDragPosition: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; +return s; +}, +dragSwipeableComponents: function(e) { +this.$.swipeableComponents.applyStyle("left", e + "px"); +}, +startSwipe: function(e) { +e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); +}, +dragPersistentItem: function(e) { +var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); +this.$.swipeableComponents.applyStyle("left", n + "px"); +}, +dragFinishPersistentItem: function(e) { +var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; +this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); +}, +setPersistentItemOrigin: function(e) { +this.persistentItemOrigin = e == 1 ? "left" : "right"; +}, +calcPercentageDragged: function(e) { +return Math.abs(e / this.$.swipeableComponents.getBounds().width); +}, +swipe: function(e) { +this.swipeComplete = !0, this.animateSwipe(0, e); +}, +backOutSwipe: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; +this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; +}, +bounceItem: function(e) { +var t = this.$.swipeableComponents.getBounds(); +t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); +}, +slideAwayItem: function() { +var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; +this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +clearSwipeables: function() { +this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +completeSwipe: function(e) { +this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ +index: this.swipeIndex, +xDirection: this.swipeDirection +})), this.swipeIndex = null, this.swipeDirection = null; +}, +animateSwipe: function(e, t) { +var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; +this.stopAnimateSwipe(); +var u = enyo.bind(this, function() { +var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); +i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { +this.completeSwipe(); +}), this.completeSwipeDelayMS)); +}); +this.job = enyo.requestAnimationFrame(u); +}, +stopAnimateSwipe: function() { +this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); +} +}); + +// PulldownList.js + +enyo.kind({ +name: "enyo.PulldownList", +kind: "List", +touch: !0, +pully: null, +pulldownTools: [ { +name: "pulldown", +classes: "enyo-list-pulldown", +components: [ { +name: "puller", +kind: "Puller" +} ] +} ], +events: { +onPullStart: "", +onPullCancel: "", +onPull: "", +onPullRelease: "", +onPullComplete: "" +}, +handlers: { +onScrollStart: "scrollStartHandler", +onScrollStop: "scrollStopHandler", +ondragfinish: "dragfinish" +}, +pullingMessage: "Pull down to refresh...", +pulledMessage: "Release to refresh...", +loadingMessage: "Loading...", +pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", +pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", +loadingIconClass: "", +create: function() { +var e = { +kind: "Puller", +showing: !1, +text: this.loadingMessage, +iconClass: this.loadingIconClass, +onCreate: "setPully" +}; +this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); +}, +initComponents: function() { +this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); +}, +resetStrategyKind: function() { +return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; +}, +setPully: function(e, t) { +this.pully = t.originator; +}, +scrollStartHandler: function() { +this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; +}, +scroll: function(e, t) { +var n = this.inherited(arguments); +this.completingPull && this.pully.setShowing(!1); +var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); +return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; +}, +scrollStopHandler: function() { +this.completingPull && (this.completingPull = !1, this.doPullComplete()); +}, +dragfinish: function() { +if (this.firedPull) { +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); +} +}, +completePull: function() { +this.completingPull = !0; +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(this.pullHeight), e.start(); +}, +pullStart: function() { +this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); +}, +pull: function() { +this.setPulled(), this.doPull(); +}, +pullCancel: function() { +this.setPulling(), this.doPullCancel(); +}, +pullRelease: function() { +this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); +}, +setPulling: function() { +this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); +}, +setPulled: function() { +this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); +} +}), enyo.kind({ +name: "enyo.Puller", +classes: "enyo-puller", +published: { +text: "", +iconClass: "" +}, +events: { +onCreate: "" +}, +components: [ { +name: "icon" +}, { +name: "text", +tag: "span", +classes: "enyo-puller-text" +} ], +create: function() { +this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); +}, +textChanged: function() { +this.$.text.setContent(this.text); +}, +iconClassChanged: function() { +this.$.icon.setClasses(this.iconClass); +} +}); + +// AroundList.js + +enyo.kind({ +name: "enyo.AroundList", +kind: "enyo.List", +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "aboveClient" +}, { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "belowClient" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0px;" +} ] +} ], +aboveComponents: null, +initComponents: function() { +this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { +owner: this.owner +}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { +owner: this.owner +}); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; +n += r, t.applyStyle(this.pageBound, n + "px"); +}, +scrollToContentStart: function() { +var e = this.bottomUp ? this.belowHeight : this.aboveHeight; +this.setScrollPosition(e); +} +}); + +// Slideable.js + +enyo.kind({ +name: "enyo.Slideable", +kind: "Control", +published: { +axis: "h", +value: 0, +unit: "px", +min: 0, +max: 0, +accelerated: "auto", +overMoving: !0, +draggable: !0 +}, +events: { +onAnimateFinish: "", +onChange: "" +}, +preventDragPropagation: !1, +tools: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorComplete" +} ], +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +kDragScalar: 1, +dragEventProp: "dx", +unitModifier: !1, +canTransform: !1, +create: function() { +this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); +}, +initComponents: function() { +this.createComponents(this.tools), this.inherited(arguments); +}, +rendered: function() { +this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); +}, +resizeHandler: function() { +this.inherited(arguments), this.updateDragScalar(); +}, +canModifyUnit: function() { +if (!this.canTransform) { +var e = this.getInitialStyleValue(this.hasNode(), this.boundary); +e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); +} +}, +getInitialStyleValue: function(e, t) { +var n = enyo.dom.getComputedStyle(e); +return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; +}, +updateBounds: function(e, t) { +var n = {}; +n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); +}, +updateDragScalar: function() { +if (this.unit == "%") { +var e = this.getBounds()[this.dimension]; +this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); +} +}, +transformChanged: function() { +this.canTransform = enyo.dom.canTransform(); +}, +acceleratedChanged: function() { +enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); +}, +axisChanged: function() { +var e = this.axis == "h"; +this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; +}, +setInlineStyles: function(e, t) { +var n = {}; +this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); +}, +valueChanged: function(e) { +var t = this.value; +this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); +}, +getAnimator: function() { +return this.$.animator; +}, +isAtMin: function() { +return this.value <= this.calcMin(); +}, +isAtMax: function() { +return this.value >= this.calcMax(); +}, +calcMin: function() { +return this.min; +}, +calcMax: function() { +return this.max; +}, +clampValue: function(e) { +var t = this.calcMin(), n = this.calcMax(); +return Math.max(t, Math.min(e, n)); +}, +dampValue: function(e) { +return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); +}, +dampBound: function(e, t, n) { +var r = e; +return r * n < t * n && (r = t + (r - t) / 4), r; +}, +percentToPixels: function(e, t) { +return Math.floor(t / 100 * e); +}, +pixelsToPercent: function(e) { +var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; +return e / t * 100; +}, +shouldDrag: function(e) { +return this.draggable && e[this.shouldDragProp]; +}, +isOob: function(e) { +return e > this.calcMax() || e < this.calcMin(); +}, +dragstart: function(e, t) { +if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; +}, +drag: function(e, t) { +if (this.dragging) { +t.preventDefault(); +var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; +return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; +} +}, +dragfinish: function(e, t) { +if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; +}, +completeDrag: function(e) { +this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); +}, +isAnimating: function() { +return this.$.animator.isAnimating(); +}, +play: function(e, t) { +this.$.animator.play({ +startValue: e, +endValue: t, +node: this.hasNode() +}); +}, +animateTo: function(e) { +this.play(this.value, e); +}, +animateToMin: function() { +this.animateTo(this.calcMin()); +}, +animateToMax: function() { +this.animateTo(this.calcMax()); +}, +animateToMinMax: function(e) { +e ? this.animateToMin() : this.animateToMax(); +}, +animatorStep: function(e) { +return this.setValue(e.value), !0; +}, +animatorComplete: function(e) { +return this.doAnimateFinish(e), !0; +}, +toggleMinMax: function() { +this.animateToMinMax(!this.isAtMin()); +} +}); + +// Arranger.js + +enyo.kind({ +name: "enyo.Arranger", +kind: "Layout", +layoutClass: "enyo-arranger", +accelerated: "auto", +dragProp: "ddx", +dragDirectionProp: "xDirection", +canDragProp: "horizontal", +incrementalPoints: !1, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n._arranger = null; +this.inherited(arguments); +}, +arrange: function(e, t) {}, +size: function() {}, +start: function() { +var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; +if (this.incrementalPoints) { +var r = Math.abs(t - e) - 2, i = e; +while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; +} +n.push(this.container.toIndex); +}, +finish: function() {}, +calcArrangementDifference: function(e, t, n, r) {}, +canDragEvent: function(e) { +return e[this.canDragProp]; +}, +calcDragDirection: function(e) { +return e[this.dragDirectionProp]; +}, +calcDrag: function(e) { +return e[this.dragProp]; +}, +drag: function(e, t, n, r, i) { +var s = this.measureArrangementDelta(-e, t, n, r, i); +return s; +}, +measureArrangementDelta: function(e, t, n, r, i) { +var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; +return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; +}, +_arrange: function(e) { +this.containerBounds || this.reflow(); +var t = this.getOrderedControls(e); +this.arrange(t, e); +}, +arrangeControl: function(e, t) { +e._arranger = enyo.mixin(e._arranger || {}, t); +}, +flow: function() { +this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { +enyo.dom.accelerate(n, this.accelerated); +if (enyo.platform.safari) { +var r = n.children; +for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); +} +} +}, +reflow: function() { +var e = this.container.hasNode(); +this.containerBounds = e ? { +width: e.clientWidth, +height: e.clientHeight +} : {}, this.size(); +}, +flowArrangement: function() { +var e = this.container.arrangement; +if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); +}, +flowControl: function(e, t) { +enyo.Arranger.positionControl(e, t); +var n = t.opacity; +n != null && enyo.Arranger.opacifyControl(e, n); +}, +getOrderedControls: function(e) { +var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; +for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); +return this.controlsIndex = t, i; +}, +statics: { +positionControl: function(e, t, n) { +var r = n || "px"; +if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { +var i = t.left, s = t.top; +i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { +translateX: i || null, +translateY: s || null +}); +} else e.setBounds(t, n); +}, +opacifyControl: function(e, t) { +var n = t; +n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); +} +} +}); + +// CardArranger.js + +enyo.kind({ +name: "enyo.CardArranger", +kind: "Arranger", +layoutClass: "enyo-arranger enyo-arranger-fit", +calcArrangementDifference: function(e, t, n, r) { +return this.containerBounds.width; +}, +arrange: function(e, t) { +for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { +opacity: s +}); +}, +start: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); +this.inherited(arguments); +} +}); + +// CardSlideInArranger.js + +enyo.kind({ +name: "enyo.CardSlideInArranger", +kind: "CardArranger", +start: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +var i = this.container.fromIndex; +t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +arrange: function(e, t) { +var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; +for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { +left: l +}); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null +}); +this.inherited(arguments); +} +}); + +// CarouselArranger.js + +enyo.kind({ +name: "enyo.CarouselArranger", +kind: "Arranger", +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; +n.height -= t.top + t.bottom, n.width -= t.left + t.right; +var a; +for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); +if (a) { +var f = n.width - s; +a.width = f >= 0 ? f : a.width; +} +for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ +top: t.top, +bottom: t.bottom, +width: u.fit ? u.width : null +}); +}, +arrange: function(e, t) { +this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); +}, +arrangeNoWrap: function(e, t) { +var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; +for (n = u, i = 0; s = o[n]; n++) { +i += s.width + s.marginWidth; +if (i > a) break; +} +var f = a - i, l = 0; +if (f > 0) { +var c = u; +for (n = u - 1, r = 0; s = o[n]; n--) { +r += s.width + s.marginWidth; +if (f - r <= 0) { +l = f - r, u = n; +break; +} +} +} +var h, p; +for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { +left: -h +}) : (this.arrangeControl(s, { +left: Math.floor(p) +}), p += h); +}, +arrangeWrap: function(e, t) { +for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { +left: r +}), r += s.width + s.marginWidth; +}, +calcArrangementDifference: function(e, t, n, r) { +var i = Math.abs(e % this.c$.length); +return t[i].left - r[i].left; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// CollapsingArranger.js + +enyo.kind({ +name: "enyo.CollapsingArranger", +kind: "CarouselArranger", +peekWidth: 0, +size: function() { +this.clearLastSize(), this.inherited(arguments); +}, +clearLastSize: function() { +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); +}, +constructor: function() { +this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; +}, +arrange: function(e, t) { +var n = this.container.getPanels(); +for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { +left: i + u * this.peekWidth +}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { +left: i +}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { +left: i - t +}); +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels().length - 1; +return Math.abs(r[i].left - t[i].left); +}, +flowControl: function(e, t) { +this.inherited(arguments); +if (this.container.realtimeFit) { +var n = this.container.getPanels(), r = n.length - 1, i = n[r]; +e == i && this.fitControl(e, t.left); +} +}, +finish: function() { +this.inherited(arguments); +if (!this.container.realtimeFit && this.containerBounds) { +var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; +this.fitControl(r, t[n].left); +} +}, +fitControl: function(e, t) { +e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); +} +}); + +// DockRightArranger.js + +enyo.kind({ +name: "enyo.DockRightArranger", +kind: "Arranger", +basePanel: !1, +overlap: 0, +layoutWidth: 0, +constructor: function() { +this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; +n.width -= t.left + t.right; +var o = n.width, u = e.length; +this.container.transitionPositions = {}; +for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; +for (r = 0; s = e[r]; r++) { +r === 0 && this.container.basePanel && s.setBounds({ +width: o +}), s.setBounds({ +top: t.top, +bottom: t.bottom +}); +for (j = 0; s = e[j]; j++) { +var a; +if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { +if (r !== j) break; +var f = o > this.layoutWidth ? this.overlap : 0; +a = o - e[r].width + f; +} +this.container.transitionPositions[r + "." + j] = a; +} +if (j < u) { +var l = !1; +for (k = r + 1; k < u; k++) { +var f = 0; +if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { +f = e[r].width - this.overlap; +for (i = r; i < k; i++) { +var c = f + e[i + 1].width - this.overlap; +if (!(c < o)) { +f = o; +break; +} +f = c; +} +f = o - f; +} +this.container.transitionPositions[r + "." + k] = f; +} +} +} +}, +arrange: function(e, t) { +var n, r, i = this.container.getPanels(), s = this.container.clamp(t); +for (n = 0; r = i[n]; n++) { +var o = this.container.transitionPositions[n + "." + s]; +this.arrangeControl(r, { +left: o +}); +} +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; +return s; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// OtherArrangers.js + +enyo.kind({ +name: "enyo.LeftRightArranger", +kind: "Arranger", +margin: 40, +axisSize: "width", +offAxisSize: "height", +axisPosition: "left", +constructor: function() { +this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; +for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); +}, +start: function() { +this.inherited(arguments); +var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); +for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); +}, +arrange: function(e, t) { +var n, r, i, s; +if (this.container.getPanels().length == 1) { +s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); +return; +} +var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; +for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; +}, +calcArrangementDifference: function(e, t, n, r) { +if (this.container.getPanels().length == 1) return 0; +var i = Math.abs(e % this.c$.length); +return t[i][this.axisPosition] - r[i][this.axisPosition]; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.TopBottomArranger", +kind: "LeftRightArranger", +dragProp: "ddy", +dragDirectionProp: "yDirection", +canDragProp: "vertical", +axisSize: "height", +offAxisSize: "width", +axisPosition: "top" +}), enyo.kind({ +name: "enyo.SpiralArranger", +kind: "Arranger", +incrementalPoints: !0, +inc: 20, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; +for (var i = 0, s; s = e[i]; i++) s.setBounds({ +width: n, +height: r +}); +}, +arrange: function(e, t) { +var n = this.inc; +for (var r = 0, i = e.length, s; s = e[r]; r++) { +var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; +this.arrangeControl(s, { +left: o, +top: u +}); +} +}, +start: function() { +this.inherited(arguments); +var e = this.getOrderedControls(this.container.toIndex); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.controlWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.GridArranger", +kind: "Arranger", +incrementalPoints: !0, +colWidth: 100, +colHeight: 100, +size: function() { +var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; +for (var r = 0, i; i = e[r]; r++) i.setBounds({ +width: t, +height: n +}); +}, +arrange: function(e, t) { +var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; +for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { +left: n * a, +top: r * o +}); +}, +flowControl: function(e, t) { +this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.colWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// Panels.js + +enyo.kind({ +name: "enyo.Panels", +classes: "enyo-panels", +published: { +index: 0, +draggable: !0, +animate: !0, +wrap: !1, +arrangerKind: "CardArranger", +narrowFit: !0 +}, +events: { +onTransitionStart: "", +onTransitionFinish: "" +}, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onscroll: "domScroll" +}, +tools: [ { +kind: "Animator", +onStep: "step", +onEnd: "completed" +} ], +fraction: 0, +create: function() { +this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); +}, +rendered: function() { +this.inherited(arguments), enyo.makeBubble(this, "scroll"); +}, +domScroll: function(e, t) { +this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); +}, +initComponents: function() { +this.createChrome(this.tools), this.inherited(arguments); +}, +arrangerKindChanged: function() { +this.setLayoutKind(this.arrangerKind); +}, +narrowFitChanged: function() { +this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); +}, +destroy: function() { +this.destroying = !0, this.inherited(arguments); +}, +removeControl: function(e) { +this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); +}, +isPanel: function() { +return !0; +}, +flow: function() { +this.arrangements = [], this.inherited(arguments); +}, +reflow: function() { +this.arrangements = [], this.inherited(arguments), this.refresh(); +}, +getPanels: function() { +var e = this.controlParent || this; +return e.children; +}, +getActive: function() { +var e = this.getPanels(), t = this.index % e.length; +return t < 0 && (t += e.length), e[t]; +}, +getAnimator: function() { +return this.$.animator; +}, +setIndex: function(e) { +this.setPropertyValue("index", e, "indexChanged"); +}, +setIndexDirect: function(e) { +this.setIndex(e), this.completed(); +}, +previous: function() { +this.setIndex(this.index - 1); +}, +next: function() { +this.setIndex(this.index + 1); +}, +clamp: function(e) { +var t = this.getPanels().length - 1; +return this.wrap ? e : Math.max(0, Math.min(e, t)); +}, +indexChanged: function(e) { +this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ +startValue: this.fraction +})) : this.refresh())); +}, +step: function(e) { +this.fraction = e.value, this.stepTransition(); +}, +completed: function() { +this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +dragstart: function(e, t) { +if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; +}, +drag: function(e, t) { +this.dragging && (t.preventDefault(), this.dragTransition(t)); +}, +dragfinish: function(e, t) { +this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); +}, +dragstartTransition: function(e) { +if (!this.$.animator.isAnimating()) { +var t = this.fromIndex = this.index; +this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); +} else this.verifyDragTransition(e); +this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); +}, +dragTransition: function(e) { +var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; +a, this.fraction += u; +var f = this.fraction; +if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; +this.stepTransition(); +}, +dragfinishTransition: function(e) { +this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); +}, +verifyDragTransition: function(e) { +var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); +if (t > 0) { +var i = n; +n = r, r = i; +} +n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; +}, +refresh: function() { +this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +startTransition: function() { +this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); +}, +finishTransition: function() { +this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); +}, +fireTransitionStart: function() { +var e = this.startTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { +fromIndex: this.fromIndex, +toIndex: this.toIndex +}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); +}, +fireTransitionFinish: function() { +var e = this.finishTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { +fromIndex: this.lastIndex, +toIndex: this.index +}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; +}, +stepTransition: function() { +if (this.hasNode()) { +var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); +t -= n; +var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); +this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); +} +}, +fetchArrangement: function(e) { +return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; +}, +readArrangement: function(e) { +var t = []; +for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); +return t; +}, +statics: { +isScreenNarrow: function() { +return enyo.dom.getWindowWidth() <= 800; +}, +lerp: function(e, t, n) { +var r = []; +for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); +return r; +}, +lerpObject: function(e, t, n) { +var r = enyo.clone(e), i, s; +if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); +return r; +} +} +}); + +// Node.js + +enyo.kind({ +name: "enyo.Node", +published: { +expandable: !1, +expanded: !1, +icon: "", +onlyIconExpands: !1, +selected: !1 +}, +style: "padding: 0 0 0 16px;", +content: "Node", +defaultKind: "Node", +classes: "enyo-node", +components: [ { +name: "icon", +kind: "Image", +showing: !1 +}, { +kind: "Control", +name: "caption", +Xtag: "span", +style: "display: inline-block; padding: 4px;", +allowHtml: !0 +}, { +kind: "Control", +name: "extra", +tag: "span", +allowHtml: !0 +} ], +childClient: [ { +kind: "Control", +name: "box", +classes: "enyo-node-box", +Xstyle: "border: 1px solid orange;", +components: [ { +kind: "Control", +name: "client", +classes: "enyo-node-client", +Xstyle: "border: 1px solid lightblue;" +} ] +} ], +handlers: { +ondblclick: "dblclick" +}, +events: { +onNodeTap: "nodeTap", +onNodeDblClick: "nodeDblClick", +onExpand: "nodeExpand", +onDestroyed: "nodeDestroyed" +}, +create: function() { +this.inherited(arguments), this.selectedChanged(), this.iconChanged(); +}, +destroy: function() { +this.doDestroyed(), this.inherited(arguments); +}, +initComponents: function() { +this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); +}, +contentChanged: function() { +this.$.caption.setContent(this.content); +}, +iconChanged: function() { +this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); +}, +selectedChanged: function() { +this.addRemoveClass("enyo-selected", this.selected); +}, +rendered: function() { +this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); +}, +addNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent(n); +this.$.client.render(); +}, +addTextNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent({ +content: n +}); +this.$.client.render(); +}, +tap: function(e, t) { +return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; +}, +dblclick: function(e, t) { +return this.doNodeDblClick(), !0; +}, +toggleExpanded: function() { +this.setExpanded(!this.expanded); +}, +quickCollapse: function() { +this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); +var e = this.$.client.getBounds().height; +this.$.client.setBounds({ +top: -e +}); +}, +_expand: function() { +this.addClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), this.$.client.setBounds({ +top: 0 +}), setTimeout(enyo.bind(this, function() { +this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); +}), 225); +}, +_collapse: function() { +this.removeClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), setTimeout(enyo.bind(this, function() { +this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ +top: -e +}); +}), 25); +}, +expandedChanged: function(e) { +if (!this.expandable) this.expanded = !1; else { +var t = { +expanded: this.expanded +}; +this.doExpand(t), t.wait || this.effectExpanded(); +} +}, +effectExpanded: function() { +this.$.client && (this.expanded ? this._expand() : this._collapse()); +} +}); + +// ImageViewPin.js + +enyo.kind({ +name: "enyo.ImageViewPin", +kind: "enyo.Control", +published: { +highlightAnchorPoint: !1, +anchor: { +top: 0, +left: 0 +}, +position: { +top: 0, +left: 0 +} +}, +style: "position:absolute;z-index:1000;width:0px;height:0px;", +handlers: { +onPositionPin: "reAnchor" +}, +create: function() { +this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); +}, +styleClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); +}, +positionClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); +}, +highlightAnchorPointChanged: function() { +this.addRemoveClass("pinDebug", this.highlightAnchorPoint); +}, +anchorChanged: function() { +var e = null, t = null; +for (t in this.anchor) { +e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); +if (!e) continue; +this.anchor[t + "Coords"] = { +value: e[1], +units: e[2] || "px" +}; +} +}, +reAnchor: function(e, t) { +var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; +this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); +} +}); + +// ImageView.js + +enyo.kind({ +name: "enyo.ImageView", +kind: enyo.Scroller, +touchOverscroll: !1, +thumb: !1, +animate: !0, +verticalDragPropagation: !0, +horizontalDragPropagation: !0, +published: { +scale: "auto", +disableZoom: !1, +src: undefined +}, +events: { +onZoom: "" +}, +touch: !0, +preventDragPropagation: !1, +handlers: { +ondragstart: "dragPropagation" +}, +components: [ { +name: "animator", +kind: "Animator", +onStep: "zoomAnimationStep", +onEnd: "zoomAnimationEnd" +}, { +name: "viewport", +style: "overflow:hidden;min-height:100%;min-width:100%;", +classes: "enyo-fit", +ongesturechange: "gestureTransform", +ongestureend: "saveState", +ontap: "singleTap", +ondblclick: "doubleClick", +onmousewheel: "mousewheel", +components: [ { +kind: "Image", +ondown: "down" +} ] +} ], +create: function() { +this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); +}, +down: function(e, t) { +t.preventDefault(); +}, +dragPropagation: function(e, t) { +var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; +return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); +}, +mousewheel: function(e, t) { +t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; +var n = (this.maxScale - this.minScale) / 10, r = this.scale; +if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); +return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; +}, +srcChanged: function() { +this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); +}, +imageLoaded: function(e) { +this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); +}, +resizeHandler: function() { +this.inherited(arguments), this.$.image.src && this.scaleChanged(); +}, +scaleChanged: function() { +var e = this.hasNode(); +if (e) { +this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; +var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; +this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); +} +this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); +}, +imageError: function(e) { +enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); +}, +alignImage: function() { +if (this.fitAlignment && this.fitAlignment === "center") { +var e = this.getScrollBounds(); +this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); +} +}, +gestureTransform: function(e, t) { +this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); +}, +calcEventLocation: function(e) { +var t = { +x: 0, +y: 0 +}; +if (e && this.hasNode()) { +var n = this.node.getBoundingClientRect(); +t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); +} +return t; +}, +transformImage: function(e) { +this.tapped = !1; +var t = this.imageBounds || this.innerImageBounds(e); +this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px" +}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; +var n, r; +this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); +if (this.canTransform) { +var i = { +scale: e +}; +this.canAccelerate ? i = enyo.mixin({ +translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" +}, i) : i = enyo.mixin({ +translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" +}, i), enyo.dom.transform(this.$.image, i); +} else this.$.image.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px", +left: this.imageBounds.left + "px", +top: this.imageBounds.top + "px" +}); +this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); +}, +limitScale: function(e) { +return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; +}, +innerImageBounds: function(e) { +var t = this.originalWidth * e, n = this.originalHeight * e, r = { +x: 0, +y: 0, +transX: 0, +transY: 0 +}; +return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { +left: r.x + r.transX, +top: r.y + r.transY, +width: t, +height: n, +x: r.x, +y: r.y +}; +}, +saveState: function(e, t) { +var n = this.scale; +this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null; +}, +doubleClick: function(e, t) { +enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); +}, +singleTap: function(e, t) { +setTimeout(enyo.bind(this, function() { +this.tapped = !1; +}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; +}, +smartZoom: function(e, t) { +var n = this.hasNode(), r = this.$.image.hasNode(); +if (n && r && this.hasNode() && !this.disableZoom) { +var i = this.scale; +this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); +if (this.animate) { +var s = { +x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, +y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height +}; +this.$.animator.play({ +duration: 350, +ratioLock: s, +baseScale: i, +deltaScale: this.scale - i +}); +} else this.transformImage(this.scale), this.doZoom({ +scale: this.scale +}); +} +}, +zoomAnimationStep: function(e, t) { +var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; +this.transformImage(n); +}, +zoomAnimationEnd: function(e, t) { +this.doZoom({ +scale: this.scale +}), this.$.animator.ratioLock = undefined; +}, +positionClientControls: function(e) { +this.waterfallDown("onPositionPin", { +scale: e, +bounds: this.imageBounds +}); +} +}); + +// ImageCarousel.js + +enyo.kind({ +name: "enyo.ImageCarousel", +kind: enyo.Panels, +arrangerKind: "enyo.CarouselArranger", +defaultScale: "auto", +disableZoom: !1, +lowMemory: !1, +published: { +images: [] +}, +handlers: { +onTransitionStart: "transitionStart", +onTransitionFinish: "transitionFinish" +}, +create: function() { +this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); +}, +initContainers: function() { +for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ +name: "container" + e, +style: "height:100%; width:100%;" +}), this.$["container" + e].render()); +for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); +this.imageCount = this.images.length; +}, +loadNearby: function() { +var e = this.getBufferRange(); +for (var t in e) this.loadImageView(e[t]); +}, +getBufferRange: function() { +var e = []; +if (this.layout.containerBounds) { +var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; +o = this.index - 1, u = 0, a = n.width * t; +while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; +o = this.index, u = 0, a = n.width * (t + 1); +while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; +} +return e; +}, +reflow: function() { +this.inherited(arguments), this.loadNearby(); +}, +loadImageView: function(e) { +return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ +name: "image" + e, +kind: "ImageView", +scale: this.defaultScale, +disableZoom: this.disableZoom, +src: this.images[e], +verticalDragPropagation: !1, +style: "height:100%; width:100%;" +}, { +owner: this +}), this.$["image" + e].render())), this.$["image" + e]; +}, +setImages: function(e) { +this.setPropertyValue("images", e, "imagesChanged"); +}, +imagesChanged: function() { +this.initContainers(), this.loadNearby(); +}, +indexChanged: function() { +this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); +}, +transitionStart: function(e, t) { +if (t.fromIndex == t.toIndex) return !0; +}, +transitionFinish: function(e, t) { +this.loadNearby(), this.lowMemory && this.cleanupMemory(); +}, +getActiveImage: function() { +return this.getImageByIndex(this.index); +}, +getImageByIndex: function(e) { +return this.$["image" + e] || this.loadImageView(e); +}, +cleanupMemory: function() { +var e = getBufferRange(); +for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); +} +}); + +// Icon.js + +enyo.kind({ +name: "onyx.Icon", +published: { +src: "", +disabled: !1 +}, +classes: "onyx-icon", +create: function() { +this.inherited(arguments), this.src && this.srcChanged(), this.disabledChanged(); +}, +disabledChanged: function() { +this.addRemoveClass("disabled", this.disabled); +}, +srcChanged: function() { +this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); +} +}); + +// Button.js + +enyo.kind({ +name: "onyx.Button", +kind: "enyo.Button", +classes: "onyx-button enyo-unselectable", +create: function() { +enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +} +}); + +// IconButton.js + +enyo.kind({ +name: "onyx.IconButton", +kind: "onyx.Icon", +published: { +active: !1 +}, +classes: "onyx-icon-button", +create: function() { +enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +}, +rendered: function() { +this.inherited(arguments), this.activeChanged(); +}, +tap: function() { +if (this.disabled) return !0; +this.setActive(!0); +}, +activeChanged: function() { +this.bubble("onActivate"); +} +}); + +// Checkbox.js + +enyo.kind({ +name: "onyx.Checkbox", +classes: "onyx-checkbox", +kind: enyo.Checkbox, +tag: "div", +handlers: { +onclick: "" +}, +tap: function(e, t) { +return this.disabled || (this.setChecked(!this.getChecked()), this.bubble("onchange")), !this.disabled; +}, +dragstart: function() {} +}); + +// Drawer.js + +enyo.kind({ +name: "onyx.Drawer", +published: { +open: !0, +orient: "v", +animated: !0 +}, +style: "overflow: hidden; position: relative;", +tools: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorEnd" +}, { +name: "client", +style: "position: relative;", +classes: "enyo-border-box" +} ], +create: function() { +this.inherited(arguments), this.animatedChanged(), this.openChanged(); +}, +initComponents: function() { +this.createChrome(this.tools), this.inherited(arguments); +}, +animatedChanged: function() { +!this.animated && this.hasNode() && this.$.animator.isAnimating() && (this.$.animator.stop(), this.animatorEnd()); +}, +openChanged: function() { +this.$.client.show(); +if (this.hasNode()) if (this.$.animator.isAnimating()) this.$.animator.reverse(); else { +var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left"; +this.applyStyle(t, null); +var r = this.hasNode()[e ? "scrollHeight" : "scrollWidth"]; +this.animated ? this.$.animator.play({ +startValue: this.open ? 0 : r, +endValue: this.open ? r : 0, +dimension: t, +position: n +}) : this.animatorEnd(); +} else this.$.client.setShowing(this.open); +}, +animatorStep: function(e) { +if (this.hasNode()) { +var t = e.dimension; +this.node.style[t] = this.domStyles[t] = e.value + "px"; +} +var n = this.$.client.hasNode(); +if (n) { +var r = e.position, i = this.open ? e.endValue : e.startValue; +n.style[r] = this.$.client.domStyles[r] = e.value - i + "px"; +} +this.container && this.container.resized(); +}, +animatorEnd: function() { +if (!this.open) this.$.client.hide(); else { +this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); +var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left", r = this.$.client.hasNode(); +r && (r.style[n] = this.$.client.domStyles[n] = null), this.node && (this.node.style[t] = this.domStyles[t] = null); +} +this.container && this.container.resized(); +} +}); + +// Grabber.js + +enyo.kind({ +name: "onyx.Grabber", +classes: "onyx-grabber" +}); + +// Groupbox.js + +enyo.kind({ +name: "onyx.Groupbox", +classes: "onyx-groupbox" +}), enyo.kind({ +name: "onyx.GroupboxHeader", +classes: "onyx-groupbox-header" +}); + +// Input.js + +enyo.kind({ +name: "onyx.Input", +kind: "enyo.Input", +classes: "onyx-input" +}); + +// Popup.js + +enyo.kind({ +name: "onyx.Popup", +kind: "Popup", +classes: "onyx-popup", +published: { +scrimWhenModal: !0, +scrim: !1, +scrimClassName: "" +}, +statics: { +count: 0 +}, +defaultZ: 120, +showingChanged: function() { +this.showing ? (onyx.Popup.count++, this.applyZIndex()) : onyx.Popup.count > 0 && onyx.Popup.count--, this.showHideScrim(this.showing), this.inherited(arguments); +}, +showHideScrim: function(e) { +if (this.floating && (this.scrim || this.modal && this.scrimWhenModal)) { +var t = this.getScrim(); +if (e) { +var n = this.getScrimZIndex(); +this._scrimZ = n, t.showAtZIndex(n); +} else t.hideAtZIndex(this._scrimZ); +enyo.call(t, "addRemoveClass", [ this.scrimClassName, t.showing ]); +} +}, +getScrimZIndex: function() { +return this.findZIndex() - 1; +}, +getScrim: function() { +return this.modal && this.scrimWhenModal && !this.scrim ? onyx.scrimTransparent.make() : onyx.scrim.make(); +}, +applyZIndex: function() { +this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1, this.applyStyle("z-index", this._zIndex); +}, +findZIndex: function() { +var e = this.defaultZ; +return this._zIndex ? e = this._zIndex : this.hasNode() && (e = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || e), this._zIndex = e; +} +}); + +// TextArea.js + +enyo.kind({ +name: "onyx.TextArea", +kind: "enyo.TextArea", +classes: "onyx-textarea" +}); + +// RichText.js + +enyo.kind({ +name: "onyx.RichText", +kind: "enyo.RichText", +classes: "onyx-richtext" +}); + +// InputDecorator.js + +enyo.kind({ +name: "onyx.InputDecorator", +kind: "enyo.ToolDecorator", +tag: "label", +classes: "onyx-input-decorator", +published: { +alwaysLooksFocused: !1 +}, +handlers: { +onDisabledChange: "disabledChange", +onfocus: "receiveFocus", +onblur: "receiveBlur" +}, +create: function() { +this.inherited(arguments), this.updateFocus(!1); +}, +alwaysLooksFocusedChanged: function(e) { +this.updateFocus(this.focus); +}, +updateFocus: function(e) { +this.focused = e, this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); +}, +receiveFocus: function() { +this.updateFocus(!0); +}, +receiveBlur: function() { +this.updateFocus(!1); +}, +disabledChange: function(e, t) { +this.addRemoveClass("onyx-disabled", t.originator.disabled); +} +}); + +// Tooltip.js + +enyo.kind({ +name: "onyx.Tooltip", +kind: "onyx.Popup", +classes: "onyx-tooltip below left-arrow", +autoDismiss: !1, +showDelay: 500, +defaultLeft: -6, +handlers: { +onRequestShowTooltip: "requestShow", +onRequestHideTooltip: "requestHide" +}, +requestShow: function() { +return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; +}, +cancelShow: function() { +clearTimeout(this.showJob); +}, +requestHide: function() { +return this.cancelShow(), this.inherited(arguments); +}, +showingChanged: function() { +this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +adjustPosition: function(e) { +if (this.showing && this.hasNode()) { +var t = this.node.getBoundingClientRect(); +t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ +"margin-left": -t.width, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); +} +}, +resizeHandler: function() { +this.applyPosition({ +"margin-left": this.defaultLeft, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); +} +}); + +// TooltipDecorator.js + +enyo.kind({ +name: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator", +handlers: { +onenter: "enter", +onleave: "leave" +}, +enter: function() { +this.requestShowTooltip(); +}, +leave: function() { +this.requestHideTooltip(); +}, +tap: function() { +this.requestHideTooltip(); +}, +requestShowTooltip: function() { +this.waterfallDown("onRequestShowTooltip"); +}, +requestHideTooltip: function() { +this.waterfallDown("onRequestHideTooltip"); +} +}); + +// MenuDecorator.js + +enyo.kind({ +name: "onyx.MenuDecorator", +kind: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator enyo-unselectable", +handlers: { +onActivate: "activated", +onHide: "menuHidden" +}, +activated: function(e, t) { +this.requestHideTooltip(), t.originator.active && (this.menuActive = !0, this.activator = t.originator, this.activator.addClass("active"), this.requestShowMenu()); +}, +requestShowMenu: function() { +this.waterfallDown("onRequestShowMenu", { +activator: this.activator +}); +}, +requestHideMenu: function() { +this.waterfallDown("onRequestHideMenu"); +}, +menuHidden: function() { +this.menuActive = !1, this.activator && (this.activator.setActive(!1), this.activator.removeClass("active")); +}, +enter: function(e) { +this.menuActive || this.inherited(arguments); +}, +leave: function(e, t) { +this.menuActive || this.inherited(arguments); +} +}); + +// Menu.js + +enyo.kind({ +name: "onyx.Menu", +kind: "onyx.Popup", +modal: !0, +defaultKind: "onyx.MenuItem", +classes: "onyx-menu", +published: { +maxHeight: 200, +scrolling: !0 +}, +handlers: { +onActivate: "itemActivated", +onRequestShowMenu: "requestMenuShow", +onRequestHideMenu: "requestHide" +}, +childComponents: [ { +name: "client", +kind: "enyo.Scroller", +strategyKind: "TouchScrollStrategy" +} ], +showOnTop: !1, +scrollerName: "client", +create: function() { +this.inherited(arguments), this.maxHeightChanged(); +}, +initComponents: function() { +this.scrolling && this.createComponents(this.childComponents, { +isChrome: !0 +}), this.inherited(arguments); +}, +getScroller: function() { +return this.$[this.scrollerName]; +}, +maxHeightChanged: function() { +this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); +}, +itemActivated: function(e, t) { +return t.originator.setActive(!1), !0; +}, +showingChanged: function() { +this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(!0); +}, +requestMenuShow: function(e, t) { +if (this.floating) { +var n = t.activator.hasNode(); +if (n) { +var r = this.activatorOffset = this.getPageOffset(n); +this.applyPosition({ +top: r.top + (this.showOnTop ? 0 : r.height), +left: r.left, +width: r.width +}); +} +} +return this.show(), !0; +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +getPageOffset: function(e) { +var t = e.getBoundingClientRect(), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; +return { +top: t.top + n, +left: t.left + r, +height: i, +width: s +}; +}, +adjustPosition: function() { +if (this.showing && this.hasNode()) { +this.scrolling && !this.showOnTop && this.getScroller().setMaxHeight(this.maxHeight + "px"), this.removeClass("onyx-menu-up"), this.floating || this.applyPosition({ +left: "auto" +}); +var e = this.node.getBoundingClientRect(), t = e.height === undefined ? e.bottom - e.top : e.height, n = window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight, r = window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; +this.menuUp = e.top + t > n && n - e.bottom < e.top - t, this.addRemoveClass("onyx-menu-up", this.menuUp); +if (this.floating) { +var i = this.activatorOffset; +this.menuUp ? this.applyPosition({ +top: i.top - t + (this.showOnTop ? i.height : 0), +bottom: "auto" +}) : e.top < i.top && i.top + (this.showOnTop ? 0 : i.height) + t < n && this.applyPosition({ +top: i.top + (this.showOnTop ? 0 : i.height), +bottom: "auto" +}); +} +e.right > r && (this.floating ? this.applyPosition({ +left: r - e.width +}) : this.applyPosition({ +left: -(e.right - r) +})), e.left < 0 && (this.floating ? this.applyPosition({ +left: 0, +right: "auto" +}) : this.getComputedStyleValue("right") == "auto" ? this.applyPosition({ +left: -e.left +}) : this.applyPosition({ +right: e.left +})); +if (this.scrolling && !this.showOnTop) { +e = this.node.getBoundingClientRect(); +var s; +this.menuUp ? s = this.maxHeight < e.bottom ? this.maxHeight : e.bottom : s = e.top + this.maxHeight < n ? this.maxHeight : n - e.top, this.getScroller().setMaxHeight(s + "px"); +} +} +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +}, +requestHide: function() { +this.setShowing(!1); +} +}); + +// MenuItem.js + +enyo.kind({ +name: "onyx.MenuItem", +kind: "enyo.Button", +events: { +onSelect: "", +onItemContentChange: "" +}, +classes: "onyx-menu-item", +tag: "div", +create: function() { +this.inherited(arguments), this.active && this.bubble("onActivate"); +}, +tap: function(e) { +this.inherited(arguments), this.bubble("onRequestHideMenu"), this.doSelect({ +selected: this, +content: this.content +}); +}, +contentChanged: function(e) { +this.inherited(arguments), this.doItemContentChange({ +content: this.content +}); +} +}); + +// PickerDecorator.js + +enyo.kind({ +name: "onyx.PickerDecorator", +kind: "onyx.MenuDecorator", +classes: "onyx-picker-decorator", +defaultKind: "onyx.PickerButton", +handlers: { +onChange: "change" +}, +change: function(e, t) { +this.waterfallDown("onChange", t); +} +}); + +// PickerButton.js + +enyo.kind({ +name: "onyx.PickerButton", +kind: "onyx.Button", +handlers: { +onChange: "change" +}, +change: function(e, t) { +t.content !== undefined && this.setContent(t.content); +} +}); + +// Picker.js + +enyo.kind({ +name: "onyx.Picker", +kind: "onyx.Menu", +classes: "onyx-picker enyo-unselectable", +published: { +selected: null +}, +events: { +onChange: "" +}, +handlers: { +onItemContentChange: "itemContentChange" +}, +floating: !0, +showOnTop: !0, +initComponents: function() { +this.setScrolling(!0), this.inherited(arguments); +}, +showingChanged: function() { +this.getScroller().setShowing(this.showing), this.inherited(arguments), this.showing && this.selected && this.scrollToSelected(); +}, +scrollToSelected: function() { +this.getScroller().scrollToControl(this.selected, !this.menuUp); +}, +itemActivated: function(e, t) { +return this.processActivatedItem(t.originator), this.inherited(arguments); +}, +processActivatedItem: function(e) { +e.active && this.setSelected(e); +}, +selectedChanged: function(e) { +e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ +selected: this.selected, +content: this.selected.content +})); +}, +itemContentChange: function(e, t) { +t.originator == this.selected && this.doChange({ +selected: this.selected, +content: this.selected.content +}); +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +} +}); + +// FlyweightPicker.js + +enyo.kind({ +name: "onyx.FlyweightPicker", +kind: "onyx.Picker", +classes: "onyx-flyweight-picker", +published: { +count: 0 +}, +events: { +onSetupItem: "", +onSelect: "" +}, +handlers: { +onSelect: "itemSelect" +}, +components: [ { +name: "scroller", +kind: "enyo.Scroller", +strategyKind: "TouchScrollStrategy", +components: [ { +name: "flyweight", +kind: "FlyweightRepeater", +noSelect: !0, +ontap: "itemTap" +} ] +} ], +scrollerName: "scroller", +initComponents: function() { +this.controlParentName = "flyweight", this.inherited(arguments), this.$.flyweight.$.client.children[0].setActive(!0); +}, +create: function() { +this.inherited(arguments), this.countChanged(); +}, +rendered: function() { +this.inherited(arguments), this.selectedChanged(); +}, +scrollToSelected: function() { +var e = this.$.flyweight.fetchRowNode(this.selected); +this.getScroller().scrollToNode(e, !this.menuUp); +}, +countChanged: function() { +this.$.flyweight.count = this.count; +}, +processActivatedItem: function(e) { +this.item = e; +}, +selectedChanged: function(e) { +if (!this.item) return; +e != null && (this.item.removeClass("selected"), this.$.flyweight.renderRow(e)); +var t; +this.selected != null && (this.item.addClass("selected"), this.$.flyweight.renderRow(this.selected), this.item.removeClass("selected"), t = this.$.flyweight.fetchRowNode(this.selected)), this.doChange({ +selected: this.selected, +content: t && t.textContent || this.item.content +}); +}, +itemTap: function(e, t) { +this.setSelected(t.rowIndex), this.doSelect({ +selected: this.item, +content: this.item.content +}); +}, +itemSelect: function(e, t) { +if (t.originator != this) return !0; +} +}); + +// DatePicker.js + +enyo.kind({ +name: "onyx.DatePicker", +classes: "onyx-toolbar-inline", +published: { +disabled: !1, +locale: "en_us", +dayHidden: !1, +monthHidden: !1, +yearHidden: !1, +minYear: 1900, +maxYear: 2099, +value: null +}, +events: { +onSelect: "" +}, +create: function() { +this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); +}, +initDefaults: function() { +var e = [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; +enyo.g11n && (this._tf = new enyo.g11n.Fmts({ +locale: this.locale +}), e = this._tf.getMonthFields()), this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : "mdy"), this.dayHiddenChanged(), this.monthHiddenChanged(), this.yearHiddenChanged(); +var t = this.value = this.value || new Date; +for (var n = 0, r; r = e[n]; n++) this.$.monthPicker.createComponent({ +content: r, +value: n, +active: n == t.getMonth() +}); +var i = t.getFullYear(); +this.$.yearPicker.setSelected(i - this.minYear); +for (n = 1; n <= this.monthLength(t.getYear(), t.getMonth()); n++) this.$.dayPicker.createComponent({ +content: n, +value: n, +active: n == t.getDate() +}); +}, +monthLength: function(e, t) { +return 32 - (new Date(e, t, 32)).getDate(); +}, +setupYear: function(e, t) { +this.$.year.setContent(this.minYear + t.index); +}, +setupPickers: function(e) { +var t = e.split(""), n, r, i; +for (r = 0, i = t.length; r < i; r++) { +n = t[r]; +switch (n) { +case "d": +this.createDay(); +break; +case "m": +this.createMonth(); +break; +case "y": +this.createYear(); +break; +default: +} +} +}, +createYear: function() { +var e = this.maxYear - this.minYear; +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateYear", +components: [ { +classes: "onyx-datepicker-year", +name: "yearPickerButton", +disabled: this.disabled +}, { +name: "yearPicker", +kind: "onyx.FlyweightPicker", +count: ++e, +onSetupItem: "setupYear", +components: [ { +name: "year" +} ] +} ] +}); +}, +createMonth: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateMonth", +components: [ { +classes: "onyx-datepicker-month", +name: "monthPickerButton", +disabled: this.disabled +}, { +name: "monthPicker", +kind: "onyx.Picker" +} ] +}); +}, +createDay: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateDay", +components: [ { +classes: "onyx-datepicker-day", +name: "dayPickerButton", +disabled: this.disabled +}, { +name: "dayPicker", +kind: "onyx.Picker" +} ] +}); +}, +localeChanged: function() { +this.refresh(); +}, +dayHiddenChanged: function() { +this.$.dayPicker.getParent().setShowing(this.dayHidden ? !1 : !0); +}, +monthHiddenChanged: function() { +this.$.monthPicker.getParent().setShowing(this.monthHidden ? !1 : !0); +}, +yearHiddenChanged: function() { +this.$.yearPicker.getParent().setShowing(this.yearHidden ? !1 : !0); +}, +minYearChanged: function() { +this.refresh(); +}, +maxYearChanged: function() { +this.refresh(); +}, +valueChanged: function() { +this.refresh(); +}, +disabledChanged: function() { +this.$.yearPickerButton.setDisabled(this.disabled), this.$.monthPickerButton.setDisabled(this.disabled), this.$.dayPickerButton.setDisabled(this.disabled); +}, +updateDay: function(e, t) { +var n = this.calcDate(this.value.getFullYear(), this.value.getMonth(), t.selected.value); +return this.doSelect({ +name: this.name, +value: n +}), this.setValue(n), !0; +}, +updateMonth: function(e, t) { +var n = this.calcDate(this.value.getFullYear(), t.selected.value, this.value.getDate()); +return this.doSelect({ +name: this.name, +value: n +}), this.setValue(n), !0; +}, +updateYear: function(e, t) { +if (t.originator.selected != -1) { +var n = this.calcDate(this.minYear + t.originator.selected, this.value.getMonth(), this.value.getDate()); +this.doSelect({ +name: this.name, +value: n +}), this.setValue(n); +} +return !0; +}, +calcDate: function(e, t, n) { +return new Date(e, t, n, this.value.getHours(), this.value.getMinutes(), this.value.getSeconds(), this.value.getMilliseconds()); +}, +refresh: function() { +this.destroyClientControls(), this.initDefaults(), this.render(); +} +}); + +// TimePicker.js + +enyo.kind({ +name: "onyx.TimePicker", +classes: "onyx-toolbar-inline", +published: { +disabled: !1, +locale: "en_us", +is24HrMode: null, +value: null +}, +events: { +onSelect: "" +}, +create: function() { +this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); +}, +initDefaults: function() { +var e = "AM", t = "PM"; +this.is24HrMode == null && (this.is24HrMode = !1), enyo.g11n && (this._tf = new enyo.g11n.Fmts({ +locale: this.locale +}), e = this._tf.getAmCaption(), t = this._tf.getPmCaption(), this.is24HrMode == null && (this.is24HrMode = !this._tf.isAmPm())), this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : "hma"); +var n = this.value = this.value || new Date, r; +if (!this.is24HrMode) { +var i = n.getHours(); +i = i === 0 ? 12 : i; +for (r = 1; r <= 12; r++) this.$.hourPicker.createComponent({ +content: r, +value: r, +active: r == (i > 12 ? i % 12 : i) +}); +} else for (r = 0; r < 24; r++) this.$.hourPicker.createComponent({ +content: r, +value: r, +active: r == n.getHours() +}); +for (r = 0; r <= 59; r++) this.$.minutePicker.createComponent({ +content: r < 10 ? "0" + r : r, +value: r, +active: r == n.getMinutes() +}); +n.getHours() >= 12 ? this.$.ampmPicker.createComponents([ { +content: e +}, { +content: t, +active: !0 +} ]) : this.$.ampmPicker.createComponents([ { +content: e, +active: !0 +}, { +content: t +} ]), this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); +}, +setupPickers: function(e) { +var t = e.split(""), n, r, i; +for (r = 0, i = t.length; r < i; r++) { +n = t[r]; +switch (n) { +case "h": +this.createHour(); +break; +case "m": +this.createMinute(); +break; +case "a": +this.createAmPm(); +break; +default: +} +} +}, +createHour: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateHour", +components: [ { +classes: "onyx-timepicker-hour", +name: "hourPickerButton", +disabled: this.disabled +}, { +name: "hourPicker", +kind: "onyx.Picker" +} ] +}); +}, +createMinute: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateMinute", +components: [ { +classes: "onyx-timepicker-minute", +name: "minutePickerButton", +disabled: this.disabled +}, { +name: "minutePicker", +kind: "onyx.Picker" +} ] +}); +}, +createAmPm: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateAmPm", +components: [ { +classes: "onyx-timepicker-ampm", +name: "ampmPickerButton", +disabled: this.disabled +}, { +name: "ampmPicker", +kind: "onyx.Picker" +} ] +}); +}, +disabledChanged: function() { +this.$.hourPickerButton.setDisabled(this.disabled), this.$.minutePickerButton.setDisabled(this.disabled), this.$.ampmPickerButton.setDisabled(this.disabled); +}, +localeChanged: function() { +this.is24HrMode = null, this.refresh(); +}, +is24HrModeChanged: function() { +this.refresh(); +}, +valueChanged: function() { +this.refresh(); +}, +updateHour: function(e, t) { +var n = t.selected.value; +if (!this.is24HrMode) { +var r = this.$.ampmPicker.getParent().controlAtIndex(0).content; +n = n + (n == 12 ? -12 : 0) + (this.isAm(r) ? 0 : 12); +} +return this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +updateMinute: function(e, t) { +return this.value = this.calcTime(this.value.getHours(), t.selected.value), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +updateAmPm: function(e, t) { +var n = this.value.getHours(); +return this.is24HrMode || (n += n > 11 ? this.isAm(t.content) ? -12 : 0 : this.isAm(t.content) ? 0 : 12), this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +calcTime: function(e, t) { +return new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), e, t, this.value.getSeconds(), this.value.getMilliseconds()); +}, +isAm: function(e) { +var t, n, r; +try { +t = this._tf.getAmCaption(), n = this._tf.getPmCaption(); +} catch (i) { +t = "AM", n = "PM"; +} +return e == t ? !0 : !1; +}, +refresh: function() { +this.destroyClientControls(), this.initDefaults(), this.render(); +} +}); + +// RadioButton.js + +enyo.kind({ +name: "onyx.RadioButton", +kind: "Button", +classes: "onyx-radiobutton" +}); + +// RadioGroup.js + +enyo.kind({ +name: "onyx.RadioGroup", +kind: "Group", +defaultKind: "onyx.RadioButton", +highlander: !0 +}); + +// ToggleButton.js + +enyo.kind({ +name: "onyx.ToggleButton", +classes: "onyx-toggle-button", +published: { +active: !1, +value: !1, +onContent: "On", +offContent: "Off", +disabled: !1 +}, +events: { +onChange: "" +}, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +components: [ { +name: "contentOn", +classes: "onyx-toggle-content on" +}, { +name: "contentOff", +classes: "onyx-toggle-content off" +}, { +classes: "onyx-toggle-button-knob" +} ], +create: function() { +this.inherited(arguments), this.value = Boolean(this.value || this.active), this.onContentChanged(), this.offContentChanged(), this.disabledChanged(); +}, +rendered: function() { +this.inherited(arguments), this.updateVisualState(); +}, +updateVisualState: function() { +this.addRemoveClass("off", !this.value), this.$.contentOn.setShowing(this.value), this.$.contentOff.setShowing(!this.value), this.setActive(this.value); +}, +valueChanged: function() { +this.updateVisualState(), this.doChange({ +value: this.value +}); +}, +activeChanged: function() { +this.setValue(this.active), this.bubble("onActivate"); +}, +onContentChanged: function() { +this.$.contentOn.setContent(this.onContent || ""), this.$.contentOn.addRemoveClass("empty", !this.onContent); +}, +offContentChanged: function() { +this.$.contentOff.setContent(this.offContent || ""), this.$.contentOff.addRemoveClass("empty", !this.onContent); +}, +disabledChanged: function() { +this.addRemoveClass("disabled", this.disabled); +}, +updateValue: function(e) { +this.disabled || this.setValue(e); +}, +tap: function() { +this.updateValue(!this.value); +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, this.dragged = !1, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = t.dx; +return Math.abs(n) > 10 && (this.updateValue(n > 0), this.dragged = !0), !0; +} +}, +dragfinish: function(e, t) { +this.dragging = !1, this.dragged && t.preventTap(); +} +}); + +// ToggleIconButton.js + +enyo.kind({ +name: "onyx.ToggleIconButton", +kind: "onyx.Icon", +published: { +active: !1, +value: !1 +}, +events: { +onChange: "" +}, +classes: "onyx-icon-button onyx-icon-toggle", +activeChanged: function() { +this.addRemoveClass("active", this.value), this.bubble("onActivate"); +}, +updateValue: function(e) { +this.disabled || (this.setValue(e), this.doChange({ +value: this.value +})); +}, +tap: function() { +this.updateValue(!this.value); +}, +valueChanged: function() { +this.setActive(this.value); +}, +create: function() { +this.inherited(arguments), this.value = Boolean(this.value || this.active); +}, +rendered: function() { +this.inherited(arguments), this.valueChanged(), this.removeClass("onyx-icon"); +} +}); + +// Toolbar.js + +enyo.kind({ +name: "onyx.Toolbar", +classes: "onyx onyx-toolbar onyx-toolbar-inline", +create: function() { +this.inherited(arguments), this.hasClass("onyx-menu-toolbar") && enyo.platform.android >= 4 && this.applyStyle("position", "static"); +} +}); + +// Tooltip.js + +enyo.kind({ +name: "onyx.Tooltip", +kind: "onyx.Popup", +classes: "onyx-tooltip below left-arrow", +autoDismiss: !1, +showDelay: 500, +defaultLeft: -6, +handlers: { +onRequestShowTooltip: "requestShow", +onRequestHideTooltip: "requestHide" +}, +requestShow: function() { +return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; +}, +cancelShow: function() { +clearTimeout(this.showJob); +}, +requestHide: function() { +return this.cancelShow(), this.inherited(arguments); +}, +showingChanged: function() { +this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +adjustPosition: function(e) { +if (this.showing && this.hasNode()) { +var t = this.node.getBoundingClientRect(); +t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ +"margin-left": -t.width, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); +} +}, +resizeHandler: function() { +this.applyPosition({ +"margin-left": this.defaultLeft, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); +} +}); + +// TooltipDecorator.js + +enyo.kind({ +name: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator", +handlers: { +onenter: "enter", +onleave: "leave" +}, +enter: function() { +this.requestShowTooltip(); +}, +leave: function() { +this.requestHideTooltip(); +}, +tap: function() { +this.requestHideTooltip(); +}, +requestShowTooltip: function() { +this.waterfallDown("onRequestShowTooltip"); +}, +requestHideTooltip: function() { +this.waterfallDown("onRequestHideTooltip"); +} +}); + +// ProgressBar.js + +enyo.kind({ +name: "onyx.ProgressBar", +classes: "onyx-progress-bar", +published: { +progress: 0, +min: 0, +max: 100, +barClasses: "", +showStripes: !0, +animateStripes: !0, +increment: 0 +}, +events: { +onAnimateProgressFinish: "" +}, +components: [ { +name: "progressAnimator", +kind: "Animator", +onStep: "progressAnimatorStep", +onEnd: "progressAnimatorComplete" +}, { +name: "bar", +classes: "onyx-progress-bar-bar" +} ], +create: function() { +this.inherited(arguments), this.progressChanged(), this.barClassesChanged(), this.showStripesChanged(), this.animateStripesChanged(); +}, +barClassesChanged: function(e) { +this.$.bar.removeClass(e), this.$.bar.addClass(this.barClasses); +}, +showStripesChanged: function() { +this.$.bar.addRemoveClass("striped", this.showStripes); +}, +animateStripesChanged: function() { +this.$.bar.addRemoveClass("animated", this.animateStripes); +}, +progressChanged: function() { +this.progress = this.clampValue(this.min, this.max, this.progress); +var e = this.calcPercent(this.progress); +this.updateBarPosition(e); +}, +calcIncrement: function(e) { +return Math.round(e / this.increment) * this.increment; +}, +clampValue: function(e, t, n) { +return Math.max(e, Math.min(n, t)); +}, +calcRatio: function(e) { +return (e - this.min) / (this.max - this.min); +}, +calcPercent: function(e) { +return this.calcRatio(e) * 100; +}, +updateBarPosition: function(e) { +this.$.bar.applyStyle("width", e + "%"); +}, +animateProgressTo: function(e) { +this.$.progressAnimator.play({ +startValue: this.progress, +endValue: e, +node: this.hasNode() +}); +}, +progressAnimatorStep: function(e) { +return this.setProgress(e.value), !0; +}, +progressAnimatorComplete: function(e) { +return this.doAnimateProgressFinish(e), !0; +} +}); + +// ProgressButton.js + +enyo.kind({ +name: "onyx.ProgressButton", +kind: "onyx.ProgressBar", +classes: "onyx-progress-button", +events: { +onCancel: "" +}, +components: [ { +name: "progressAnimator", +kind: "Animator", +onStep: "progressAnimatorStep", +onEnd: "progressAnimatorComplete" +}, { +name: "bar", +classes: "onyx-progress-bar-bar onyx-progress-button-bar" +}, { +name: "client", +classes: "onyx-progress-button-client" +}, { +kind: "onyx.Icon", +src: "$lib/onyx/images/progress-button-cancel.png", +classes: "onyx-progress-button-icon", +ontap: "cancelTap" +} ], +cancelTap: function() { +this.doCancel(); +} +}); + +// Scrim.js + +enyo.kind({ +name: "onyx.Scrim", +showing: !1, +classes: "onyx-scrim enyo-fit", +floating: !1, +create: function() { +this.inherited(arguments), this.zStack = [], this.floating && this.setParent(enyo.floatingLayer); +}, +showingChanged: function() { +this.floating && this.showing && !this.hasNode() && this.render(), this.inherited(arguments); +}, +addZIndex: function(e) { +enyo.indexOf(e, this.zStack) < 0 && this.zStack.push(e); +}, +removeZIndex: function(e) { +enyo.remove(e, this.zStack); +}, +showAtZIndex: function(e) { +this.addZIndex(e), e !== undefined && this.setZIndex(e), this.show(); +}, +hideAtZIndex: function(e) { +this.removeZIndex(e); +if (!this.zStack.length) this.hide(); else { +var t = this.zStack[this.zStack.length - 1]; +this.setZIndex(t); +} +}, +setZIndex: function(e) { +this.zIndex = e, this.applyStyle("z-index", e); +}, +make: function() { +return this; +} +}), enyo.kind({ +name: "onyx.scrimSingleton", +kind: null, +constructor: function(e, t) { +this.instanceName = e, enyo.setObject(this.instanceName, this), this.props = t || {}; +}, +make: function() { +var e = new onyx.Scrim(this.props); +return enyo.setObject(this.instanceName, e), e; +}, +showAtZIndex: function(e) { +var t = this.make(); +t.showAtZIndex(e); +}, +hideAtZIndex: enyo.nop, +show: function() { +var e = this.make(); +e.show(); +} +}), new onyx.scrimSingleton("onyx.scrim", { +floating: !0, +classes: "onyx-scrim-translucent" +}), new onyx.scrimSingleton("onyx.scrimTransparent", { +floating: !0, +classes: "onyx-scrim-transparent" +}); + +// Slider.js + +enyo.kind({ +name: "onyx.Slider", +kind: "onyx.ProgressBar", +classes: "onyx-slider", +published: { +value: 0, +lockBar: !0, +tappable: !0 +}, +events: { +onChange: "", +onChanging: "", +onAnimateFinish: "" +}, +showStripes: !1, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +moreComponents: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorComplete" +}, { +classes: "onyx-slider-taparea" +}, { +name: "knob", +classes: "onyx-slider-knob" +} ], +create: function() { +this.inherited(arguments), enyo.platform.firefoxOS && (this.moreComponents[2].ondown = "down", this.moreComponents[2].onleave = "leave"), this.createComponents(this.moreComponents), this.valueChanged(); +}, +valueChanged: function() { +this.value = this.clampValue(this.min, this.max, this.value); +var e = this.calcPercent(this.value); +this.updateKnobPosition(e), this.lockBar && this.setProgress(this.value); +}, +updateKnobPosition: function(e) { +this.$.knob.applyStyle("left", e + "%"); +}, +calcKnobPosition: function(e) { +var t = e.clientX - this.hasNode().getBoundingClientRect().left; +return t / this.getBounds().width * (this.max - this.min) + this.min; +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = this.calcKnobPosition(t); +return n = this.increment ? this.calcIncrement(n) : n, this.setValue(n), this.doChanging({ +value: this.value +}), !0; +} +}, +dragfinish: function(e, t) { +return this.dragging = !1, t.preventTap(), this.doChange({ +value: this.value +}), !0; +}, +tap: function(e, t) { +if (this.tappable) { +var n = this.calcKnobPosition(t); +return n = this.increment ? this.calcIncrement(n) : n, this.tapped = !0, this.animateTo(n), !0; +} +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +}, +animateTo: function(e) { +this.$.animator.play({ +startValue: this.value, +endValue: e, +node: this.hasNode() +}); +}, +animatorStep: function(e) { +return this.setValue(e.value), !0; +}, +animatorComplete: function(e) { +return this.tapped && (this.tapped = !1, this.doChange({ +value: this.value +})), this.doAnimateFinish(e), !0; +} +}); + +// RangeSlider.js + +enyo.kind({ +name: "onyx.RangeSlider", +kind: "onyx.ProgressBar", +classes: "onyx-slider", +published: { +rangeMin: 0, +rangeMax: 100, +rangeStart: 0, +rangeEnd: 100, +beginValue: 0, +endValue: 0 +}, +events: { +onChange: "", +onChanging: "" +}, +showStripes: !1, +showLabels: !1, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +ondown: "down" +}, +moreComponents: [ { +name: "startKnob", +classes: "onyx-slider-knob" +}, { +name: "endKnob", +classes: "onyx-slider-knob onyx-range-slider-knob" +} ], +create: function() { +this.inherited(arguments), this.createComponents(this.moreComponents), this.initControls(); +}, +rendered: function() { +this.inherited(arguments); +var e = this.calcPercent(this.beginValue); +this.updateBarPosition(e); +}, +initControls: function() { +this.$.bar.applyStyle("position", "relative"), this.refreshRangeSlider(), this.showLabels && (this.$.startKnob.createComponent({ +name: "startLabel", +kind: "onyx.RangeSliderKnobLabel" +}), this.$.endKnob.createComponent({ +name: "endLabel", +kind: "onyx.RangeSliderKnobLabel" +})); +}, +refreshRangeSlider: function() { +this.beginValue = this.calcKnobPercent(this.rangeStart), this.endValue = this.calcKnobPercent(this.rangeEnd), this.beginValueChanged(), this.endValueChanged(); +}, +calcKnobRatio: function(e) { +return (e - this.rangeMin) / (this.rangeMax - this.rangeMin); +}, +calcKnobPercent: function(e) { +return this.calcKnobRatio(e) * 100; +}, +beginValueChanged: function(e) { +if (e === undefined) { +var t = this.calcPercent(this.beginValue); +this.updateKnobPosition(t, this.$.startKnob); +} +}, +endValueChanged: function(e) { +if (e === undefined) { +var t = this.calcPercent(this.endValue); +this.updateKnobPosition(t, this.$.endKnob); +} +}, +calcKnobPosition: function(e) { +var t = e.clientX - this.hasNode().getBoundingClientRect().left; +return t / this.getBounds().width * (this.max - this.min) + this.min; +}, +updateKnobPosition: function(e, t) { +t.applyStyle("left", e + "%"), this.updateBarPosition(); +}, +updateBarPosition: function() { +if (this.$.startKnob !== undefined && this.$.endKnob !== undefined) { +var e = this.calcKnobPercent(this.rangeStart), t = this.calcKnobPercent(this.rangeEnd) - e; +this.$.bar.applyStyle("left", e + "%"), this.$.bar.applyStyle("width", t + "%"); +} +}, +calcRangeRatio: function(e) { +return e / 100 * (this.rangeMax - this.rangeMin) + this.rangeMin - this.increment / 2; +}, +swapZIndex: function(e) { +e === "startKnob" ? (this.$.startKnob.applyStyle("z-index", 1), this.$.endKnob.applyStyle("z-index", 0)) : e === "endKnob" && (this.$.startKnob.applyStyle("z-index", 0), this.$.endKnob.applyStyle("z-index", 1)); +}, +down: function(e, t) { +this.swapZIndex(e.name); +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = this.calcKnobPosition(t), r, i, s; +if (e.name === "startKnob" && n >= 0) { +if (!(n <= this.endValue && t.xDirection === -1 || n <= this.endValue)) return this.drag(this.$.endKnob, t); +this.setBeginValue(n), r = this.calcRangeRatio(this.beginValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.startKnob), this.setRangeStart(i), this.doChanging({ +value: i +}); +} else if (e.name === "endKnob" && n <= 100) { +if (!(n >= this.beginValue && t.xDirection === 1 || n >= this.beginValue)) return this.drag(this.$.startKnob, t); +this.setEndValue(n), r = this.calcRangeRatio(this.endValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.endKnob), this.setRangeEnd(i), this.doChanging({ +value: i +}); +} +return !0; +} +}, +dragfinish: function(e, t) { +this.dragging = !1, t.preventTap(); +var n; +return e.name === "startKnob" ? (n = this.calcRangeRatio(this.beginValue), this.doChange({ +value: n, +startChanged: !0 +})) : e.name === "endKnob" && (n = this.calcRangeRatio(this.endValue), this.doChange({ +value: n, +startChanged: !1 +})), !0; +}, +rangeMinChanged: function() { +this.refreshRangeSlider(); +}, +rangeMaxChanged: function() { +this.refreshRangeSlider(); +}, +rangeStartChanged: function() { +this.refreshRangeSlider(); +}, +rangeEndChanged: function() { +this.refreshRangeSlider(); +}, +setStartLabel: function(e) { +this.$.startKnob.waterfallDown("onSetLabel", e); +}, +setEndLabel: function(e) { +this.$.endKnob.waterfallDown("onSetLabel", e); +} +}), enyo.kind({ +name: "onyx.RangeSliderKnobLabel", +classes: "onyx-range-slider-label", +handlers: { +onSetLabel: "setLabel" +}, +setLabel: function(e, t) { +this.setContent(t); +} +}); + +// Item.js + +enyo.kind({ +name: "onyx.Item", +classes: "onyx-item", +tapHighlight: !0, +handlers: { +onhold: "hold", +onrelease: "release" +}, +hold: function(e, t) { +this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !0, t); +}, +release: function(e, t) { +this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !1, t); +}, +statics: { +addRemoveFlyweightClass: function(e, t, n, r, i) { +var s = r.flyweight; +if (s) { +var o = i !== undefined ? i : r.index; +s.performOnRow(o, function() { +e.addRemoveClass(t, n); +}); +} +} +} +}); + +// Spinner.js + +enyo.kind({ +name: "onyx.Spinner", +classes: "onyx-spinner", +stop: function() { +this.setShowing(!1); +}, +start: function() { +this.setShowing(!0); +}, +toggle: function() { +this.setShowing(!this.getShowing()); +} +}); + +// MoreToolbar.js + +enyo.kind({ +name: "onyx.MoreToolbar", +classes: "onyx-toolbar onyx-more-toolbar", +menuClass: "", +movedClass: "", +layoutKind: "FittableColumnsLayout", +noStretch: !0, +handlers: { +onHide: "reflow" +}, +published: { +clientLayoutKind: "FittableColumnsLayout" +}, +tools: [ { +name: "client", +noStretch: !0, +fit: !0, +classes: "onyx-toolbar-inline" +}, { +name: "nard", +kind: "onyx.MenuDecorator", +showing: !1, +onActivate: "activated", +components: [ { +kind: "onyx.IconButton", +classes: "onyx-more-button" +}, { +name: "menu", +kind: "onyx.Menu", +scrolling: !1, +classes: "onyx-more-menu" +} ] +} ], +initComponents: function() { +this.menuClass && this.menuClass.length > 0 && !this.$.menu.hasClass(this.menuClass) && this.$.menu.addClass(this.menuClass), this.createChrome(this.tools), this.inherited(arguments), this.$.client.setLayoutKind(this.clientLayoutKind); +}, +clientLayoutKindChanged: function() { +this.$.client.setLayoutKind(this.clientLayoutKind); +}, +reflow: function() { +this.inherited(arguments), this.isContentOverflowing() ? (this.$.nard.show(), this.popItem() && this.reflow()) : this.tryPushItem() ? this.reflow() : this.$.menu.children.length || (this.$.nard.hide(), this.$.menu.hide()); +}, +activated: function(e, t) { +this.addRemoveClass("active", t.originator.active); +}, +popItem: function() { +var e = this.findCollapsibleItem(); +if (e) { +this.movedClass && this.movedClass.length > 0 && !e.hasClass(this.movedClass) && e.addClass(this.movedClass), this.$.menu.addChild(e, null); +var t = this.$.menu.hasNode(); +return t && e.hasNode() && e.insertNodeInParent(t), !0; +} +}, +pushItem: function() { +var e = this.$.menu.children, t = e[0]; +if (t) { +this.movedClass && this.movedClass.length > 0 && t.hasClass(this.movedClass) && t.removeClass(this.movedClass), this.$.client.addChild(t); +var n = this.$.client.hasNode(); +if (n && t.hasNode()) { +var r, i; +for (var s = 0; s < this.$.client.children.length; s++) { +var o = this.$.client.children[s]; +if (o.toolbarIndex !== undefined && o.toolbarIndex != s) { +r = o, i = s; +break; +} +} +if (r && r.hasNode()) { +t.insertNodeInParent(n, r.node); +var u = this.$.client.children.pop(); +this.$.client.children.splice(i, 0, u); +} else t.appendNodeToParent(n); +} +return !0; +} +}, +tryPushItem: function() { +if (this.pushItem()) { +if (!this.isContentOverflowing()) return !0; +this.popItem(); +} +}, +isContentOverflowing: function() { +if (this.$.client.hasNode()) { +var e = this.$.client.children, t = e[e.length - 1].hasNode(); +if (t) return this.$.client.reflow(), t.offsetLeft + t.offsetWidth > this.$.client.node.clientWidth; +} +}, +findCollapsibleItem: function() { +var e = this.$.client.children; +for (var t = e.length - 1; c = e[t]; t--) { +if (!c.unmoveable) return c; +c.toolbarIndex === undefined && (c.toolbarIndex = t); +} +} +}); + +// IntegerPicker.js + +enyo.kind({ +name: "onyx.IntegerPicker", +kind: "onyx.Picker", +published: { +value: 0, +min: 0, +max: 9 +}, +create: function() { +this.inherited(arguments), this.rangeChanged(); +}, +minChanged: function() { +this.destroyClientControls(), this.rangeChanged(), this.render(); +}, +maxChanged: function() { +this.destroyClientControls(), this.rangeChanged(), this.render(); +}, +rangeChanged: function() { +for (var e = this.min; e <= this.max; e++) this.createComponent({ +content: e, +active: e === this.value ? !0 : !1 +}); +}, +valueChanged: function(e) { +var t = this.getClientControls(), n = t.length; +this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; +for (var r = 0; r < n; r++) if (this.value === parseInt(t[r].content)) { +this.setSelected(t[r]); +break; +} +}, +selectedChanged: function(e) { +e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ +selected: this.selected, +content: this.selected.content +})), this.value = parseInt(this.selected.content); +} +}); + +// ContextualPopup.js + +enyo.kind({ +name: "onyx.ContextualPopup", +kind: "enyo.Popup", +modal: !0, +autoDismiss: !0, +floating: !1, +classes: "onyx-contextual-popup enyo-unselectable", +published: { +maxHeight: 100, +scrolling: !0, +title: undefined, +actionButtons: [] +}, +vertFlushMargin: 60, +horizFlushMargin: 50, +widePopup: 200, +longPopup: 200, +horizBuffer: 16, +events: { +onTap: "" +}, +handlers: { +onActivate: "itemActivated", +onRequestShowMenu: "requestShow", +onRequestHideMenu: "requestHide" +}, +components: [ { +name: "title", +classes: "onyx-contextual-popup-title" +}, { +classes: "onyx-contextual-popup-scroller", +components: [ { +name: "client", +kind: "enyo.Scroller", +vertical: "auto", +classes: "enyo-unselectable", +thumb: !1, +strategyKind: "TouchScrollStrategy" +} ] +}, { +name: "actionButtons", +classes: "onyx-contextual-popup-action-buttons" +} ], +scrollerName: "client", +create: function() { +this.inherited(arguments), this.maxHeightChanged(), this.titleChanged(), this.actionButtonsChanged(); +}, +getScroller: function() { +return this.$[this.scrollerName]; +}, +titleChanged: function() { +this.$.title.setContent(this.title); +}, +actionButtonsChanged: function() { +for (var e = 0; e < this.actionButtons.length; e++) this.$.actionButtons.createComponent({ +kind: "onyx.Button", +content: this.actionButtons[e].content, +classes: this.actionButtons[e].classes + " onyx-contextual-popup-action-button", +name: this.actionButtons[e].name ? this.actionButtons[e].name : "ActionButton" + e, +index: e, +tap: enyo.bind(this, this.tapHandler) +}); +}, +tapHandler: function(e, t) { +return t.actionButton = !0, t.popup = this, this.bubble("ontap", t), !0; +}, +maxHeightChanged: function() { +this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); +}, +itemActivated: function(e, t) { +return t.originator.setActive(!1), !0; +}, +showingChanged: function() { +this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(); +}, +requestShow: function(e, t) { +var n = t.activator.hasNode(); +return n && (this.activatorOffset = this.getPageOffset(n)), this.show(), !0; +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +getPageOffset: function(e) { +var t = this.getBoundingRect(e), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; +return { +top: t.top + n, +left: t.left + r, +height: i, +width: s +}; +}, +adjustPosition: function() { +if (this.showing && this.hasNode()) { +this.resetPositioning(); +var e = this.getViewWidth(), t = this.getViewHeight(), n = this.vertFlushMargin, r = t - this.vertFlushMargin, i = this.horizFlushMargin, s = e - this.horizFlushMargin; +if (this.activatorOffset.top + this.activatorOffset.height < n || this.activatorOffset.top > r) { +if (this.applyVerticalFlushPositioning(i, s)) return; +if (this.applyHorizontalFlushPositioning(i, s)) return; +if (this.applyVerticalPositioning()) return; +} else if (this.activatorOffset.left + this.activatorOffset.width < i || this.activatorOffset.left > s) if (this.applyHorizontalPositioning()) return; +var o = this.getBoundingRect(this.node); +if (o.width > this.widePopup) { +if (this.applyVerticalPositioning()) return; +} else if (o.height > this.longPopup && this.applyHorizontalPositioning()) return; +if (this.applyVerticalPositioning()) return; +if (this.applyHorizontalPositioning()) return; +} +}, +initVerticalPositioning: function() { +this.resetPositioning(), this.addClass("vertical"); +var e = this.getBoundingRect(this.node), t = this.getViewHeight(); +return this.floating ? this.activatorOffset.top < t / 2 ? (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height, +bottom: "auto" +}), this.addClass("below")) : (this.applyPosition({ +top: this.activatorOffset.top - e.height, +bottom: "auto" +}), this.addClass("above")) : e.top + e.height > t && t - e.bottom < e.top - e.height ? this.addClass("above") : this.addClass("below"), e = this.getBoundingRect(this.node), e.top + e.height > t || e.top < 0 ? !1 : !0; +}, +applyVerticalPositioning: function() { +if (!this.initVerticalPositioning()) return !1; +var e = this.getBoundingRect(this.node), t = this.getViewWidth(); +if (this.floating) { +var n = this.activatorOffset.left + this.activatorOffset.width / 2 - e.width / 2; +n + e.width > t ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width - e.width +}), this.addClass("left")) : n < 0 ? (this.applyPosition({ +left: this.activatorOffset.left +}), this.addClass("right")) : this.applyPosition({ +left: n +}); +} else { +var r = this.activatorOffset.left + this.activatorOffset.width / 2 - e.left - e.width / 2; +e.right + r > t ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width - e.right +}), this.addRemoveClass("left", !0)) : e.left + r < 0 ? this.addRemoveClass("right", !0) : this.applyPosition({ +left: r +}); +} +return !0; +}, +applyVerticalFlushPositioning: function(e, t) { +if (!this.initVerticalPositioning()) return !1; +var n = this.getBoundingRect(this.node), r = this.getViewWidth(); +return this.activatorOffset.left + this.activatorOffset.width / 2 < e ? (this.activatorOffset.left + this.activatorOffset.width / 2 < this.horizBuffer ? this.applyPosition({ +left: this.horizBuffer + (this.floating ? 0 : -n.left) +}) : this.applyPosition({ +left: this.activatorOffset.width / 2 + (this.floating ? this.activatorOffset.left : 0) +}), this.addClass("right"), this.addClass("corner"), !0) : this.activatorOffset.left + this.activatorOffset.width / 2 > t ? (this.activatorOffset.left + this.activatorOffset.width / 2 > r - this.horizBuffer ? this.applyPosition({ +left: r - this.horizBuffer - n.right +}) : this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width / 2 - n.right +}), this.addClass("left"), this.addClass("corner"), !0) : !1; +}, +initHorizontalPositioning: function() { +this.resetPositioning(); +var e = this.getBoundingRect(this.node), t = this.getViewWidth(); +return this.floating ? this.activatorOffset.left + this.activatorOffset.width < t / 2 ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width +}), this.addRemoveClass("left", !0)) : (this.applyPosition({ +left: this.activatorOffset.left - e.width +}), this.addRemoveClass("right", !0)) : this.activatorOffset.left - e.width > 0 ? (this.applyPosition({ +left: this.activatorOffset.left - e.left - e.width +}), this.addRemoveClass("right", !0)) : (this.applyPosition({ +left: this.activatorOffset.width +}), this.addRemoveClass("left", !0)), this.addRemoveClass("horizontal", !0), e = this.getBoundingRect(this.node), e.left < 0 || e.left + e.width > t ? !1 : !0; +}, +applyHorizontalPositioning: function() { +if (!this.initHorizontalPositioning()) return !1; +var e = this.getBoundingRect(this.node), t = this.getViewHeight(), n = this.activatorOffset.top + this.activatorOffset.height / 2; +return this.floating ? n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 - e.height / 2, +bottom: "auto" +}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ +top: this.activatorOffset.top - this.activatorOffset.height, +bottom: "auto" +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: this.activatorOffset.top - e.height + this.activatorOffset.height * 2, +bottom: "auto" +}), this.addRemoveClass("low", !0)) : n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ +top: (this.activatorOffset.height - e.height) / 2 +}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ +top: -this.activatorOffset.height +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: e.top - e.height - this.activatorOffset.top + this.activatorOffset.height +}), this.addRemoveClass("low", !0)), !0; +}, +applyHorizontalFlushPositioning: function(e, t) { +if (!this.initHorizontalPositioning()) return !1; +var n = this.getBoundingRect(this.node), r = this.getViewWidth(); +return this.floating ? this.activatorOffset.top < innerHeight / 2 ? (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 - n.height +}), this.addRemoveClass("low", !0)) : n.top + n.height > innerHeight && innerHeight - n.bottom < n.top - n.height ? (this.applyPosition({ +top: n.top - n.height - this.activatorOffset.top - this.activatorOffset.height / 2 +}), this.addRemoveClass("low", !0)) : (this.applyPosition({ +top: this.activatorOffset.height / 2 +}), this.addRemoveClass("high", !0)), this.activatorOffset.left + this.activatorOffset.width < e ? (this.addClass("left"), this.addClass("corner"), !0) : this.activatorOffset.left > t ? (this.addClass("right"), this.addClass("corner"), !0) : !1; +}, +getBoundingRect: function(e) { +var t = e.getBoundingClientRect(); +return !t.width || !t.height ? { +left: t.left, +right: t.right, +top: t.top, +bottom: t.bottom, +width: t.right - t.left, +height: t.bottom - t.top +} : t; +}, +getViewHeight: function() { +return window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight; +}, +getViewWidth: function() { +return window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; +}, +resetPositioning: function() { +this.removeClass("right"), this.removeClass("left"), this.removeClass("high"), this.removeClass("low"), this.removeClass("corner"), this.removeClass("below"), this.removeClass("above"), this.removeClass("vertical"), this.removeClass("horizontal"), this.applyPosition({ +left: "auto" +}), this.applyPosition({ +top: "auto" +}); +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +}, +requestHide: function() { +this.setShowing(!1); +} +}); + +// App.js + +enyo.kind({ +name: "App", +kind: "FittableRows", +fit: !0, +components: [ { +kind: "onyx.Toolbar", +content: "Hello World" +}, { +kind: "enyo.Scroller", +fit: !0, +components: [ { +name: "main", +classes: "nice-padding", +allowHtml: !0 +} ] +}, { +kind: "onyx.Toolbar", +components: [ { +kind: "onyx.Button", +content: "Tap me", +ontap: "helloWorldTap" +} ] +} ], +helloWorldTap: function(e, t) { +this.$.main.addContent("The button was tapped.
    "); +} +}); diff --git a/build/enyo.css b/build/enyo.css new file mode 100644 index 0000000..6d05291 --- /dev/null +++ b/build/enyo.css @@ -0,0 +1,181 @@ + +/* ../source/dom/dom.css */ + +/* things we always want */ +body { + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; +} + +/* allow hw-accelerated scrolling on platforms that support it */ +body.webkitOverflowScrolling { + -webkit-overflow-scrolling: touch; +} + +/* for apps */ +.enyo-document-fit { + margin: 0; + height: 100%; + /* note: giving html overflow: auto is odd and was only ever done to avoid duplication + however, android 4.04 sometimes does not hide nodes when their display is set to none + if document is overflow auto. + */ + position: relative; +} + +.enyo-body-fit { + margin: 0; + height: 100%; + /* helps prevent ios page scroll */ + overflow: auto; + position: relative; +} + +.enyo-no-touch-action { + -ms-touch-action: none; +} + +/* reset */ + +button { + font-size: inherit; + font-family: inherit; +} +button::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* user selection */ + +.enyo-unselectable { + cursor: default; + -ms-user-select: none; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; +} + +.enyo-unselectable::selection, .enyo-unselectable ::selection { + color: transparent; +} + +.enyo-selectable { + cursor: auto; + -ms-user-select: element; + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; +} + +.enyo-selectable::selection, .enyo-selectable ::selection { + background: #3297FD; + color: #FFF; +} + +/* layout */ + +body .enyo-fit { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.enyo-clip { + overflow: hidden; +} + +.enyo-border-box { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* compositing */ + +.enyo-composite { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); +} + + +/* ../source/touch/Thumb.css */ + +.enyo-thumb { + position: absolute; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; + background: #333; + border: 1px solid #666; + opacity: 0.75; + z-index: 1; +} + +.enyo-vthumb { + top: 0; + right: 2px; + width: 4px; +} + +.enyo-hthumb { + left: 0; + bottom: 2px; + height: 4px; +} + + +/* ../source/touch/Scroller.css */ + +.enyo-scroller { + position: relative; +} + +.enyo-fit.enyo-scroller { + position: absolute; +} + +.enyo-touch-scroller { + overflow: hidden; +} + +.enyo-touch-strategy-container { + overflow: hidden; +} + +.enyo-scrollee-fit { + height: 100%; +} + +/* ../source/ui/ui.css */ + +.enyo-inline, .enyo-tool-decorator { + display: inline-block; +} + +.enyo-children-inline > *, .enyo-tool-decorator > * { + display: inline-block; +} + +.enyo-children-middle > *, .enyo-tool-decorator > * { + vertical-align: middle; +} + +.enyo-positioned { + position: relative; +} + +.enyo-fill { + position: relative; + width: 100%; + height: 100%; +} + +.enyo-popup { + position: absolute; + z-index: 10; +} diff --git a/build/enyo.js b/build/enyo.js new file mode 100644 index 0000000..909a6ad --- /dev/null +++ b/build/enyo.js @@ -0,0 +1,4308 @@ + +// enyo.js + +(function() { +var e = "enyo.js"; +enyo = window.enyo || {}, enyo.locateScript = function(e) { +var t = document.getElementsByTagName("script"); +for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { +i = r.getAttribute("src") || ""; +if (i.slice(-s) == e) return r.located = !0, { +path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), +node: r +}; +} +}, enyo.args = enyo.args || {}; +var t = enyo.locateScript(e); +if (t) { +enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); +for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; +} +})(); + +// ../../loader.js + +(function() { +enyo = window.enyo || {}, enyo.pathResolverFactory = function() { +this.paths = {}; +}, enyo.pathResolverFactory.prototype = { +addPath: function(e, t) { +return this.paths[e] = t; +}, +addPaths: function(e) { +if (e) for (var t in e) this.addPath(t, e[t]); +}, +includeTrailingSlash: function(e) { +return e && e.slice(-1) !== "/" ? e + "/" : e; +}, +rewritePattern: /\$([^\/\\]*)(\/)?/g, +rewrite: function(e) { +var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { +return t = !0, n(r[i]) || ""; +}, s = e; +do t = !1, s = s.replace(this.rewritePattern, i); while (t); +return s; +} +}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { +this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; +}, enyo.loaderFactory.prototype = { +verbose: !1, +loadScript: function(e) { +this.machine.script(e); +}, +loadSheet: function(e) { +this.machine.sheet(e); +}, +loadPackage: function(e) { +this.machine.script(e); +}, +report: function() {}, +load: function() { +this.more({ +index: 0, +depends: arguments || [] +}); +}, +more: function(e) { +if (e && this.continueBlock(e)) return; +var t = this.stack.pop(); +t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); +}, +finish: function() { +this.packageFolder = "", this.verbose && console.log("-------------- fini"); +for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); +}, +continueBlock: function(e) { +while (e.index < e.depends.length) { +var t = e.depends[e.index++]; +if (t) if (typeof t == "string") { +if (this.require(t, e)) return !0; +} else this.pathResolver.addPaths(t); +} +}, +require: function(e, t) { +var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); +n = r + n; +if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { +if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; +this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); +} +}, +getPathPrefix: function(e) { +var t = e.slice(0, 1); +return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; +}, +requireStylesheet: function(e) { +this.sheets.push(e), this.loadSheet(e); +}, +requireScript: function(e, t) { +this.modules.push({ +packageName: this.packageName, +rawPath: e, +path: t +}), this.loadScript(t); +}, +decodePackagePath: function(e) { +var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; +if (s.length) { +var a = s.pop() || s.pop() || ""; +a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; +for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { +s.splice(o, 1); +break; +} +n = s.join("/"); +for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { +s = s.slice(o + 1); +break; +} +for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); +t = s.join("-"); +} +return { +alias: t, +target: n, +folder: r, +manifest: i +}; +}, +aliasPackage: function(e) { +var t = this.decodePackagePath(e); +this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ +name: t.alias, +folder: t.folder +})), this.packageFolder = t.folder; +}, +requirePackage: function(e, t) { +t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); +} +}; +})(); + +// boot.js + +enyo.execUnsafeLocalFunction = function(e) { +typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); +}, enyo.machine = { +sheet: function(e) { +var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; +r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); +var i; +enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { +document.write(''); +}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { +less.refresh(!0); +})); +}, +script: function(e, t, n) { +if (!enyo.runtimeLoading) document.write(' + + + + + + + diff --git a/deploy.md b/deploy.md new file mode 100644 index 0000000..009c12c --- /dev/null +++ b/deploy.md @@ -0,0 +1,52 @@ +# Minification and Deployment +## Understanding and Using Minification + +Enyo comes with a minification tool based on UglifyJS, run by Node.js. + +This tool can be used to compress the framework, other libraries, and applications, and will keep load order intact as well as correct url paths in css. + +### Why compress? + +Compressing enyo apps greatly reduces load times of applications, as well as reducing overall code size. + +This way, you can be very verbose in the documentation of your source code, without that impacting the performance of your application in production. + +### What is compressed + +For enyo, the libraries, and your code: **external assets such as images will not be copied or moved**. + +Instead, the CSS url paths are fixed up to reference the new path from the build location. + +### How to compress + +To compress your application, you must run the Node.js script named `deploy.js` that comes with Enyo, as `enyo/tools/deploy.js`. + + $ node enyo/tools/deploy.js -h + +This script will run the minification tool located in `enyo/tools/minifier/minify.js`, and make a build of enyo, then a build of your app. + +Any libraries referenced in your `package.js` manifest will be built into your app's built code. + +**NOTE:** `deploy.js` expects to find a `package.js` in the root-folder of your application. It only references your app's `package.js` to keep paths correct. Do not modify this. + +### What comes out? + +After running the `deploy.js` script, a new folder `build` (you change this using the `-b` flag of the `deploy.js` script) will be located next to your `source` directory. + +In it will be 4 files: +- enyo.css +- enyo.js +- app.css +- app.js + +These files will be loaded in the given order by `index.html`. + +The output of the `deploy` scripts will minify your appliaction, and copy the necessary files into `deploy//`. + +If the libraries have a compatible `deploy.sh` or `deploy.bat` script, they will be executed, and a minimal copy will be placed in the deployment's lib folder. + +If no `deploy.(sh|bat)` script is found for the library, all of the library is copied into the lib folder to provide maximum safety. + +If you are adding a library, please add a `deploy.sh` file and `deploy.bat` file similar to the ones in `lib/onyx`. + +If no images or files are needed from the library, just include blank (and executable) copies of the deploy scripts. diff --git a/deploy/bootplate/assets/favicon.ico b/deploy/bootplate/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..52c86347fe3e10042c05374362757fa260307d50 GIT binary patch literal 1150 zcmb`FKMnyw7{#BEC=@o4NK}++2k<9R=-ogfBntOXlHdvyYK=~#aR8MgC>3JNvw6v6 zt=*BB&9}4j&HUcH{bqoSeS!e?UBfsBlmXOj*p$tLdE23F=SqbzI8JMq)4}u`6~jJl zZFFAje9-(^L+ot9~P>KuLiljZ#* * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + /* float when not stretched */ + float: left; + clear: both; +} + +/* non-floating when stretched */ +.enyo-fittable-rows-layout.enyo-stretch > * { + float: none; + clear: none; +} + +/* setting to enforce margin collapsing */ +/* NOTE: rows cannot have margin left/right */ +.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { + float: left; + clear: both; + width: 100%; + /* note: harsh resets */ + margin-left: 0 !important; + margin-right: 0 !important; +} + +.enyo-fittable-columns-layout { + position: relative; + text-align: left; + white-space: nowrap; +} + +.enyo-fittable-columns-layout.enyo-center { + text-align: center; +} + +.enyo-fittable-columns-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + vertical-align: top; + display: inline-block; + white-space: normal; +} + +.enyo-fittable-columns-layout.enyo-tool-decorator > * { + vertical-align: middle; +} + +/* repair clobbered white-space setting for pre, code */ +.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { + white-space: pre; +} + +.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { + white-space: nowrap; +} + +/* NOTE: columns cannot have margin top/bottom */ +.enyo-fittable-columns-layout.enyo-stretch > * { + height: 100%; + /* note: harsh resets */ + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/List.css */ + +.enyo-list { + position: relative; +} + +.enyo-list-port { + overflow: hidden; + position: relative; + height: 1000000px; +} + +.enyo-list-page, .enyo-list-holdingarea { + position: absolute; + left: 0; + right: 0; +} + +.enyo-list-holdingarea { + top: -10000px; +} + +.enyo-pinned-list-placeholder { + border: 1px solid red; + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-pinned-list-placeholder button { + width: 100px; height: 100%; + position: absolute; + top: 0; right: 0; +} + +.enyo-list-reorder-container { + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-animatedTopAndLeft { + -webkit-transition: top 0.1s linear, left 0.1s linear; + -moz-transition: top 0.1s linear, left 0.1s linear; + -o-transition: top 0.1s linear, left 0.1s linear; + transition: top 0.1s linear, left 0.1s linear; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/PulldownList.css */ + +.enyo-list-pulldown { + position: absolute; + bottom: 100%; + left: 0; + right: 0; +} + +.enyo-puller { + position: relative; + height: 50px; + font-size: 22px; + color: #444; + padding: 20px 0 0px 34px; +} + +.enyo-puller-text { + position: absolute; + left: 80px; + top: 22px; +} + +.enyo-puller-arrow { + position: relative; + background: #444; + width: 7px; + height: 28px; + transition: transform 0.3s; + -webkit-transition: -webkit-transform 0.3s; + -moz-transition: -moz-transform 0.3s; + -o-transition: -o-transform 0.3s; + -ms-transition: -ms-transform 0.3s; +} + +.enyo-puller-arrow:after { + content: " "; + height: 0; + width: 0; + position: absolute; + border: 10px solid transparent; + border-bottom-color: #444; + bottom: 100%; + left: 50%; + margin-left: -10px; +} + +.enyo-puller-arrow-up { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); +} + +.enyo-puller-arrow-down { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); + -ms-transform: rotate(180deg); +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/arrangers/Arranger.css */ + +.enyo-arranger { + position: relative; + overflow: hidden; +} + +.enyo-arranger.enyo-fit { + position: absolute; +} + +.enyo-arranger > * { + position: absolute; + left: 0; + top: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.enyo-arranger-fit > * { + /* override any width/height set on panels */ + width: 100% !important; + height: 100% !important; + min-width: 0 !important; + min-height: 0 !important; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/Panels.css */ + +.enyo-panels { +} + +.enyo-panels-fit-narrow { +} + +@media all and (max-width: 800px) { + .enyo-panels-fit-narrow > * { + min-width: 100%; + max-width: 100%; + } +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/tree/source/Node.css */ + +.enyo-node { + cursor: default; + padding: 4px; +} + +.enyo-node img { + vertical-align: middle; + padding-right: 6px; +} + +.enyo-node-box { + overflow: hidden; +} + +.enyo-node-client { + position: relative; +} + +.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { + -ms-transition-property: height, top; + -ms-transition-duration: 0.2s, 0.2s; + -moz-transition-property: height, top; + -moz-transition-duration: 0.2s, 0.2s; + -o-transition-property: height, top; + -o-transition-duration: 0.2s, 0.2s; + -webkit-transition-property: height, top; + -webkit-transition-duration: 0.2s, 0.2s; + transition-property: height, top; + transition-duration: 0.2s, 0.2s; +} + + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/imageview/source/ImageViewPin.css */ + + +.pinDebug { + background:yellow; + border:1px solid yellow; +} + +/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/css/onyx.less */ + +/* Onyx default parameters defined here */ +/* Fonts */ +/* ---------------------------------------*/ +/* Text Colors */ +/* ---------------------------------------*/ +/* Background Colors */ +/* ---------------------------------------*/ +/* Border Radius */ +/* ---------------------------------------*/ +/* Padding */ +/* ---------------------------------------*/ +/* Icon Sizes */ +/* ---------------------------------------*/ +/* Disabled Opacity */ +/* ---------------------------------------*/ +/* Gradient Overlays */ +/* ---------------------------------------*/ +/* Images */ +/* ---------------------------------------*/ +/* Onyx rules defined here */ +/* onyx-classes.less - combined CSS (less) files for all released Onyx controls + into single onyx.less file to avoid IE bug that allows + a maximum of 31 style sheets to be loaded before silently failing */ +.onyx { + color: #333333; + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; + font-size: 20px; + cursor: default; + background-color: #eaeaea; + /* remove automatic tap highlight color */ + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +/* prevent IE from inheriting line-height for these elements */ +.onyx button, +.onyx label, +.onyx input { + line-height: normal; +} +.onyx-selected { + background-color: #c4e3fe; +} +/* LESS pre-calculations */ +/* Individual Widget CSS */ +/* Icon.css */ +.onyx-icon, +.onyx-icon-toggle { + width: 32px; + height: 32px; + background-repeat: no-repeat; + display: inline-block; + vertical-align: middle; +} +.onyx-icon.onyx-icon-button.active, +.onyx-icon.onyx-icon-button.pressed, +.onyx-icon.onyx-icon-button:active:hover, +.onyx-icon-toggle.active { + background-position: 0 -32px; +} +.onyx-icon.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-icon.disabled:active:hover { + background-position: 0 0px; +} +/* Button.css */ +.onyx-button { + outline: 0; + color: #292929; + font-size: 16px; + text-align: center; + white-space: nowrap; + margin: 0; + padding: 6px 18px; + overflow: hidden; + border-radius: 3px; + /* for IE8 */ + + border: 1px solid #707070; + border: 1px solid rgba(15, 15, 15, 0.2); + /* + The border and the gradient interact in a strange way that + causes the bottom-border (top if the gradient is aligned top) + to be lighter than other borders. + We can fix it by using the darker bottom border below, but + then there are a few rogue pixels that end up very dark. + */ + + /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ + + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); + background: #e1e1e1 url(../lib/onyx/images/gradient.png) repeat-x bottom; + background-size: contain; + /**/ + + text-overflow: ellipsis; + /* the following cause arcane problems on IE */ + + /* + min-width: 14px; + min-height: 20px; + */ + +} +/* + IE8 can't handle these selectors in tandem: + .onyx-button.active, .onyx-button:active:not([disabled]) { + + the effect is as if .onyx-button.active doesn't exist +*/ +.onyx-button.active, +.onyx-button.pressed { + background-image: url(../lib/onyx/images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button:active:hover:not([disabled]) { + background-image: url(../lib/onyx/images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button[disabled] { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-button > img { + padding: 0px 3px; +} +/* Remove the focused inner-border style in Firefox (Windows) */ +.onyx-button::-moz-focus-inner { + border: 0; +} +/* Checkbox.css */ +.onyx-checkbox { + cursor: pointer; + height: 32px; + width: 32px; + background: url(../lib/onyx/images/checkbox.png) no-repeat; + /* reset for ? */ + + margin: 0px; + /* these entries cause toggle-button and checkbox to line up properly*/ + + display: inline-block; + vertical-align: middle; +} +.onyx-checkbox[checked] { + background-position: 0px -32px; +} +.onyx-checkbox[disabled] { + opacity: 0.4; +} +/* Grabber.css */ +.onyx-grabber { + background: url(../lib/onyx/images/grabbutton.png) no-repeat center; + width: 23px; + height: 27px; +} +/* Popup.css */ +.onyx-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; +} +.onyx-popup-decorator { + position: relative; +} +/* Groupbox.css */ +.onyx-groupbox > * { + display: block; + /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ + + border-color: #aaaaaa; + border-style: solid; + border-width: 0 1px 1px 1px; + /*padding: 10px;*/ + + /* reset styles that make 'item' look bad if they happen to be there */ + + border-radius: 0; + margin: 0; + font-size: 16px; +} +.onyx-groupbox > *:first-child { + border-top-color: #aaaaaa; + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > *:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > *:first-child:last-child { + border-radius: 4px; +} +.onyx-groupbox-header { + padding: 2px 10px; + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; + /**/ + + background-color: #4c4c4c; + border: none; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 10px; +} +.onyx-groupbox .onyx-input-decorator { + display: block; +} +.onyx-groupbox > .onyx-input-decorator { + border-color: #aaaaaa; + border-width: 0 1px 1px 1px; + border-radius: 0; +} +.onyx-groupbox > .onyx-input-decorator:first-child { + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > .onyx-input-decorator:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > .onyx-input-decorator:first-child:last-child { + border-radius: 4px; +} +/* Input.css */ +.onyx-input-decorator { + padding: 6px 8px 10px 8px; + border-radius: 3px; + border: 1px solid; + border-color: rgba(0, 0, 0, 0.1); + margin: 0; +} +.onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + border-color: rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-input-decorator.onyx-disabled { + /* FIXME: needed to color a disabled input placeholder. */ + + /*-webkit-text-fill-color: #888;*/ + + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-input-decorator > input { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > input { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > input { + cursor: default; +} +/* Menu.css */ +.onyx-menu, +.onyx.onyx-menu { + min-width: 160px; + top: 100%; + left: 0; + margin-top: 2px; + padding: 3px 0; + border-radius: 3px; +} +.onyx-menu.onyx-menu-up { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 2px; +} +.onyx-toolbar .onyx-menu { + margin-top: 11px; + border-radius: 0 0 3px 3px; +} +.onyx-toolbar .onyx-menu.onyx-menu-up { + margin-top: 0; + margin-bottom: 10px; + border-radius: 3px 3px 0 0; +} +.onyx-menu-item { + display: block; + padding: 10px; +} +.onyx-menu-item:hover { + background: #284152; +} +.onyx-menu-divider, +.onyx-menu-divider:hover { + margin: 6px 0; + padding: 0; + border-bottom: 1px solid #aaa; +} +.onyx-menu-label { + cursor: default; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-menu-label:hover { + background: none; +} +/* customize a toolbar to support menus */ +.onyx-menu-toolbar, +.onyx-toolbar.onyx-menu-toolbar { + position: relative; + z-index: 10; + overflow: visible; +} +/* Picker.css */ +.onyx-picker-decorator .onyx-button { + padding: 10px 18px; +} +.onyx-picker { + top: 0; + margin-top: -3px; + min-width: 0; + width: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + color: black; + background: #e1e1e1; +} +.onyx-picker.onyx-menu-up { + top: auto; + bottom: 0; + margin-top: 3px; + margin-bottom: -3px; +} +.onyx-picker .onyx-menu-item { + text-align: center; +} +.onyx-picker .onyx-menu-item:hover { + background-color: transparent; +} +.onyx-picker .onyx-menu-item.selected, +.onyx-picker .onyx-menu-item.active, +.onyx-picker .onyx-menu-item:active:hover { + border-top: 1px solid rgba(0, 0, 0, 0.1); + background-color: #cde7fe; + box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); +} +.onyx-picker .onyx-menu-item { + border-top: 1px solid rgba(255, 255, 255, 0.5); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, +.onyx-flyweight-picker :first-child > .onyx-menu-item { + border-top: none; +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, +.onyx-flyweight-picker :last-child > .onyx-menu-item { + border-bottom: none; +} +/* TextArea.css */ +.onyx-input-decorator > textarea { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* Remove scrollbars and resize handle */ + + resize: none; + overflow: auto; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > textarea { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > textarea { + cursor: default; +} +.onyx-textarea { + /* need >=50px for scrollbar to be usable on mac */ + + min-height: 50px; +} +/* RichText.css */ +.onyx-input-decorator > .onyx-richtext { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + min-height: 20px; + min-width: 100px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > .onyx-richtext { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > .onyx-richtext { + cursor: default; +} +/* RadioButton.css */ +.onyx-radiobutton { + padding: 8px 12px; + margin: 0; + outline: 0; + font-size: 16px; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + text-align: center; + /**/ + + background: #e7e7e7 url(../lib/onyx/images/gradient.png) repeat-x bottom; + /* IE8 */ + + border: 1px solid #333333; + border: 1px solid rgba(15, 15, 15, 0.2); + /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ + + border-right-color: rgba(0, 0, 0, 0); + box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); +} +.onyx-radiobutton:first-child { + border-radius: 3px 0 0 3px; +} +.onyx-radiobutton:last-child { + border-radius: 0px 3px 3px 0px; + /* IE8 */ + + border-right: 1px solid #333333; + border-right: 1px solid rgba(15, 15, 15, 0.2); +} +.onyx-radiobutton.active { + color: #ffffff; + background: #0091f2 url(../lib/onyx/images/gradient-invert.png) repeat-x top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); +} +/* Scrim.css */ +.onyx-scrim { + z-index: 1; + /* + note: by using pointer-events we allow tapping on scrim + while it is fading out; however, this requires any showing classes + to set pointer events to auto or scrim will not function as expected. + */ + + pointer-events: none; +} +.onyx-scrim.onyx-scrim-translucent { + pointer-events: auto; + background-color: #000000; + opacity: 0.65; + filter: alpha(opacity=65); +} +.onyx-scrim.onyx-scrim-transparent { + pointer-events: auto; + background: transparent; +} +/* TabButton.css */ +.onyx-radiobutton.onyx-tabbutton { + padding: 8px 34px; + font-size: 20px; + border-radius: 0px; +} +/* ToggleButton.css */ +.onyx-toggle-button { + display: inline-block; + height: 32px; + line-height: 32px; + min-width: 64px; + vertical-align: middle; + text-align: center; + /* */ + + border-radius: 3px; + box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); + background: #8bba3d url(../lib/onyx/images/gradient-invert.png) repeat-x bottom; + background-size: auto 100%; + /* label */ + + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; +} +.onyx-toggle-button.off { + background-color: #b1b1b1 !important; +} +.onyx-toggle-button-knob { + display: inline-block; + width: 30px; + height: 30px; + margin: 1px; + border-radius: 3px; + background: #f6f6f6 url(../lib/onyx/images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-toggle-button .onyx-toggle-button-knob { + box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: right; +} +.onyx-toggle-button.off .onyx-toggle-button-knob { + box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: left; +} +.onyx-toggle-button.disabled, +.onyx-icon-button.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-toggle-content { + min-width: 32px; + padding: 0 6px; +} +.onyx-toggle-content.empty { + padding: 0; +} +.onyx-toggle-content.off { + float: right; +} +.onyx-toggle-content.on { + float: left; +} +/* Toolbar.css */ +.onyx-toolbar { + /* + line-height is unreliable for centering, instead + use vertical-align: middle to align + elements along a common centerline and use + padding to fill out the space. + */ + + padding: 9px 8px 10px 8px; + border: 1px solid #3A3A3A; + background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; + background-size: contain; + color: #ffffff; + /**/ + + white-space: nowrap; + overflow-y: visible; + font-size: 20px; +} +.onyx-toolbar-inline > *, +.enyo-fittable-columns-layout.onyx-toolbar-inline > * { + display: inline-block; + vertical-align: middle; + margin: 4px 6px 5px; + box-sizing: border-box; +} +.onyx-toolbar .onyx-icon-button { + margin: 3px 2px 1px; +} +.onyx-toolbar .onyx-button { + color: #f2f2f2; + background-color: #555656; + border-color: rgba(15, 15, 15, 0.5); + margin-top: 0; + margin-bottom: 0; + height: 36px; +} +.onyx-toolbar .onyx-input-decorator { + margin: 1px 3px; + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); + padding: 0px 6px 5px 6px; +} +.onyx-toolbar .onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-toolbar .onyx-input-decorator .onyx-input { + color: #e5e5e5; + font-size: 14px; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus { + color: #000000; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { + color: #dddddd; +} +/* Tooltip.css */ +.onyx-tooltip { + z-index: 20; + left: 0; + padding: 4px 6px; + margin-top: 4px; + margin-left: -6px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + color: #ffffff; + background: #216593 url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; + border-radius: 3px; + white-space: nowrap; +} +/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ +.onyx-tooltip.right-arrow { + left: 30px; +} +/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ +.onyx-tooltip::before { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + left: 16px; +} +.onyx-tooltip::after { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + margin-left: -12px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ +.onyx-tooltip.below { + top: 100%; +} +.onyx-tooltip.below.right-arrow::after { + border-bottom: 6px solid #1D587F; + top: -6px; +} +.onyx-tooltip.below.left-arrow::before { + border-bottom: 6px solid #1D587F; + top: -6px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ +.onyx-tooltip.above { + top: -100%; +} +.onyx-tooltip.above.right-arrow::after { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +.onyx-tooltip.above.left-arrow::before { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +/* ProgressBar.css */ +.onyx-progress-bar { + margin: 8px; + height: 8px; + border: 1px solid rgba(15, 15, 15, 0.2); + border-radius: 3px; + background: #b8b8b8 url(../lib/onyx/images/gradient-invert.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar { + height: 100%; + border-radius: 3px; + background: #58abef url(../lib/onyx/images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar.striped { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.onyx-progress-bar-bar.striped.animated { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +/* ProgressButton.css */ +.onyx-progress-button { + position: relative; + height: 36px; + line-height: 36px; + color: #f1f1f1; + font-size: 16px; + text-overflow: ellipsis; +} +.onyx-progress-button-bar { + height: 36px; +} +.onyx-progress-button-icon { + display: inline-block; + position: absolute; + top: 2px; + right: 0; +} +.onyx-progress-button-client { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 36px; + margin-left: 8px; +} +.onyx-progress-button-client > * { + display: inline-block; +} +/* Slider.css */ +.onyx-slider { + position: relative; + margin: 8px 20px; +} +.onyx-slider-taparea { + position: absolute; + top: -11px; + height: 28px; + width: 100%; +} +.onyx-slider-knob { + position: relative; + height: 40px; + width: 40px; + background: url(../lib/onyx/images/slider-handle.png) left top no-repeat; + margin: -23px -20px; +} +.onyx-slider-knob.active, +.onyx-slider-knob.pressed, +.onyx-slider-knob:active:hover { + background-position: 0 -40px; +} +/* RangeSlider.css */ +.onyx-range-slider-knob { + top: -17px; +} +.onyx-range-slider-label { + position: relative; + top: -18px; + text-align: center; + white-space: nowrap; +} +/* Item.css */ +.onyx-item { + padding: 14px; +} +.onyx-highlight, +.onyx-highlight.onyx-swipeable-item-content { + background-color: #dedfdf; +} +.enyo-selected, +.enyo-selected.onyx-swipeable-item-content { + background-color: #c4e3fe; +} +.onyx-item.onyx-swipeable-item { + overflow: hidden; + padding: 0; +} +.onyx-swipeable-item-content { + background-color: #eaeaea; + box-sizing: border-box; + padding: 18px 6px; + min-height: 40px; +} +/* Spinner.css */ +.onyx-spinner { + width: 59px; + height: 58px; + display: inline-block; + background: url(../lib/onyx/images/spinner-dark.gif) no-repeat 0 0; +} +.onyx-spinner.onyx-light { + background: url(../lib/onyx/images/spinner-light.gif) no-repeat 0 0; +} +/* MoreToolbar.css */ +.onyx-more-toolbar { + overflow: visible; + position: relative; + z-index: 10; +} +.onyx-more-toolbar.active { + z-index: 11; +} +.onyx-more-menu { + left: auto; + right: 0px; + min-width: 0; +} +.onyx-more-toolbar .onyx-more-menu > * { + float: right; + clear: both; + margin: 5px; + margin-top: 5px; + margin-bottom: 5px; +} +.onyx-more-button { + background-image: url(../lib/onyx/images/more.png); + width: 32px; + height: 32px; +} +/* DatePicker.css */ +.onyx-datepicker-month { + min-width: 75px; +} +.onyx-datepicker-day { + min-width: 60px; +} +.onyx-datepicker-year { + min-width: 70px; +} +/* TimePicker.css */ +.onyx-timepicker-hour { + min-width: 60px; +} +.onyx-timepicker-minute { + min-width: 60px; +} +.onyx-timepicker-ampm { + min-width: 60px; +} +/* ButtonColors.css */ +.onyx-button.onyx-blue { + background-color: #35A8EE; + color: #F2F2F2; +} +.onyx-button.onyx-affirmative { + background-color: #91BA07; + color: #F2F2F2; +} +.onyx-button.onyx-negative { + background-color: #C51616; + color: #F2F2F2; +} +.onyx-button.onyx-dark { + background-color: #555656; + color: #F2F2F2; +} +.onyx-button.onyx-light { + background-color: #cacaca; + color: #2F2F2F; +} +/* ContextualPopup.css */ +.onyx-contextual-popup-title { + font-weight: bold; + padding: 24px 32px 0px; +} +.onyx-contextual-popup-scroller { + padding: 24px 32px; +} +.onyx-contextual-popup-action-buttons { + display: inline-block; + width: 100%; + text-align: center; +} +.onyx-contextual-popup-action-button { + margin-left: 5px; + margin-right: 5px; +} +.onyx-contextual-popup, +.onyx.onyx-contextual-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c; +} +/*setup the nub*/ +.onyx-contextual-popup::after { + content: ''; + position: absolute; + top: -10px; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; +} +/*for popups above activator*/ +.onyx-contextual-popup.vertical.above { + top: auto; + margin-top: -10px; + bottom: 100%; + margin-bottom: 10px; +} +/*for popups below activator*/ +.onyx-contextual-popup.vertical.below { + margin-top: 10px; +} +/*for popups on the left of the activator*/ +.onyx-contextual-popup.right.horizontal { + margin-left: -11px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.left.horizontal { + margin-left: 10px; +} +/*nub positioning*/ +/*horizontally centered nub*/ +.onyx-contextual-popup.vertical::after { + position: absolute; + left: 45%; + border-bottom: 10px solid #4c4c4c; + border-top: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +/*nub near horizontal left*/ +.onyx-contextual-popup.vertical.right::after { + left: 0%; + margin-left: 20px; +} +/*nub near horizontal right*/ +.onyx-contextual-popup.vertical.left::after { + left: 100%; + margin-left: -55px; +} +/*downward facing nub*/ +.onyx-contextual-popup.vertical.above::after { + top: 100%; + border-top: 10px solid #4c4c4c; + border-bottom: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right::after { + top: 0%; + margin-top: -10px; + border-bottom: 10px solid #4c4c4c; + border-left: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.left::after { + top: 0%; + margin-top: -10px; + border-right: 10px solid transparent; +} +/*nub positioning for left/right popups*/ +/*vertically centered nub for popups on left of activator*/ +.onyx-contextual-popup.right::after { + left: 100%; + top: 47%; + margin-right: 20px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on left of activator*/ +.onyx-contextual-popup.right.high::after { + top: 35px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on left of activator*/ +.onyx-contextual-popup.right.low::after { + top: 100%; + margin-top: -55px; + border-left: 10px solid #4C4C4C; +} +/*vertically centered nub for popups on right of activator*/ +.onyx-contextual-popup.left::after { + left: 0%; + margin-left: -20px; + top: 45%; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on right of activator*/ +.onyx-contextual-popup.left.high::after { + top: 35px; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on right of activator*/ +.onyx-contextual-popup.left.low::after { + top: 100%; + margin-top: -55px; + border-right: 10px solid #4C4C4C; +} +/*corners*/ +/*vertical top corners*/ +/*for popups on the left of the activator*/ +.onyx-contextual-popup.vertical.right.corner { + margin-left: 0px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.vertical.left.corner { + margin-left: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.vertical.below.right.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner::after { + top: 0%; + left: 100%; + margin-top: -10px; + margin-left: -19px; + border-right: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right.corner::after { + top: 0%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +/*vertical bottom corners*/ +.onyx-contextual-popup.left.above.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.right.above.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.vertical.left.above.corner::after { + top: 100%; + margin-left: -19px; + border-right: 10px solid #4C4C4C; + border-bottom: 10px solid transparent; + border-top: none; +} +.onyx-contextual-popup.vertical.right.above.corner::after { + top: 100%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-bottom: 10px solid transparent; + border-top: none; +} +/*horizontal bottom corners*/ +.onyx-contextual-popup.left.low.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.right.low.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.left.low.corner::after { + top: 100%; + left: 0%; + margin-top: -19px; + margin-left: -12px; + border-bottom: 10px solid #4c4c4c; + border-right: 10px solid #4c4c4c; +} +.onyx-contextual-popup.right.low.corner::after { + top: 100%; + left: 100%; + margin-top: -19px; + border-bottom: 10px solid#4c4c4c; + border-left: none; +} +/*horizontal top corners*/ +.onyx-contextual-popup.left.high.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.right.high.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.left.high.corner::after { + top: 0%; + left: 0%; + margin-top: -1px; + margin-left: -12px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +.onyx-contextual-popup.right.high.corner::after { + top: 0%; + left: 100%; + margin-top: -1px; + margin-left: -9px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +/* some default colors */ +.onyx-dark { + background-color: #555656; +} +.onyx-light { + background-color: #cacaca; +} +.onyx-green { + background-color: #91BA07; +} +.onyx-red { + background-color: #C51616; +} +.onyx-blue { + background-color: #35A8EE; +} + + +/* source/App.css */ + +/* + Put anything you reference with "url(../source)" in ../assets/ + This way, you can minify your application, and just remove the "source" folder for production +*/ +.nice-padding { + padding: 15px; +} diff --git a/deploy/bootplate/build/app.js b/deploy/bootplate/build/app.js new file mode 100644 index 0000000..7a17c89 --- /dev/null +++ b/deploy/bootplate/build/app.js @@ -0,0 +1,4447 @@ + +// minifier: path aliases + +enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/source/"}); + +// FittableLayout.js + +enyo.kind({ +name: "enyo.FittableLayout", +kind: "Layout", +calcFitIndex: function() { +for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; +}, +getFitControl: function() { +var e = this.container.children, t = e[this.fitIndex]; +return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; +}, +getLastControl: function() { +var e = this.container.children, t = e.length - 1, n = e[t]; +while ((n = e[t]) && !n.showing) t--; +return n; +}, +_reflow: function(e, t, n, r) { +this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); +var i = this.getFitControl(); +if (!i) return; +var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); +f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); +var l = i.getBounds(); +o = l[n] - (a && a[n] || 0); +var c = this.getLastControl(); +if (c) { +var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; +if (c != i) { +var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; +u = v - d; +} else u = h; +} +var m = s - (o + u); +i.applyStyle(e, m + "px"); +}, +reflow: function() { +this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); +} +}), enyo.kind({ +name: "enyo.FittableColumnsLayout", +kind: "FittableLayout", +orient: "h", +layoutClass: "enyo-fittable-columns-layout" +}), enyo.kind({ +name: "enyo.FittableRowsLayout", +kind: "FittableLayout", +layoutClass: "enyo-fittable-rows-layout", +orient: "v" +}); + +// FittableRows.js + +enyo.kind({ +name: "enyo.FittableRows", +layoutKind: "FittableRowsLayout", +noStretch: !1 +}); + +// FittableColumns.js + +enyo.kind({ +name: "enyo.FittableColumns", +layoutKind: "FittableColumnsLayout", +noStretch: !1 +}); + +// FlyweightRepeater.js + +enyo.kind({ +name: "enyo.FlyweightRepeater", +published: { +count: 0, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +clientClasses: "", +clientStyle: "", +rowOffset: 0 +}, +events: { +onSetupItem: "", +onRenderRow: "" +}, +bottomUp: !1, +components: [ { +kind: "Selection", +onSelect: "selectDeselect", +onDeselect: "selectDeselect" +}, { +name: "client" +} ], +create: function() { +this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); +}, +noSelectChanged: function() { +this.noSelect && this.$.selection.clear(); +}, +multiSelectChanged: function() { +this.$.selection.setMulti(this.multiSelect); +}, +clientClassesChanged: function() { +this.$.client.setClasses(this.clientClasses); +}, +clientStyleChanged: function() { +this.$.client.setStyle(this.clientStyle); +}, +setupItem: function(e) { +this.doSetupItem({ +index: e, +selected: this.isSelected(e) +}); +}, +generateChildHtml: function() { +var e = ""; +this.index = null; +for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); +return e; +}, +previewDomEvent: function(e) { +var t = this.index = this.rowForEvent(e); +e.rowIndex = e.index = t, e.flyweight = this; +}, +decorateEvent: function(e, t, n) { +var r = t && t.index != null ? t.index : this.index; +t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); +}, +tap: function(e, t) { +if (this.noSelect || t.index === -1) return; +this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); +}, +selectDeselect: function(e, t) { +this.renderRow(t.key); +}, +getSelection: function() { +return this.$.selection; +}, +isSelected: function(e) { +return this.getSelection().isSelected(e); +}, +renderRow: function(e) { +if (e < this.rowOffset || e >= this.count + this.rowOffset) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ +rowIndex: e +})); +}, +fetchRowNode: function(e) { +if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); +}, +rowForEvent: function(e) { +if (!this.hasNode()) return -1; +var t = e.target; +while (t && t !== this.node) { +var n = t.getAttribute && t.getAttribute("data-enyo-index"); +if (n !== null) return Number(n); +t = t.parentNode; +} +return -1; +}, +prepareRow: function(e) { +if (e < 0 || e >= this.count) return; +this.setupItem(e); +var t = this.fetchRowNode(e); +enyo.FlyweightRepeater.claimNode(this.$.client, t); +}, +lockRow: function() { +this.$.client.teardownChildren(); +}, +performOnRow: function(e, t, n) { +if (e < 0 || e >= this.count) return; +t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); +}, +statics: { +claimNode: function(e, t) { +var n; +t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); +for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); +} +} +}); + +// List.js + +enyo.kind({ +name: "enyo.List", +kind: "Scroller", +classes: "enyo-list", +published: { +count: 0, +rowsPerPage: 50, +bottomUp: !1, +noSelect: !1, +multiSelect: !1, +toggleSelected: !1, +fixedHeight: !1, +reorderable: !1, +centerReorderContainer: !0, +reorderComponents: [], +pinnedReorderComponents: [], +swipeableComponents: [], +enableSwipe: !1, +persistSwipeableItem: !1 +}, +events: { +onSetupItem: "", +onSetupReorderComponents: "", +onSetupPinnedReorderComponents: "", +onReorder: "", +onSetupSwipeItem: "", +onSwipeDrag: "", +onSwipe: "", +onSwipeComplete: "" +}, +handlers: { +onAnimateFinish: "animateFinish", +onRenderRow: "rowRendered", +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onup: "up", +onholdpulse: "holdpulse" +}, +rowHeight: 0, +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0;" +} ] +} ], +reorderHoldTimeMS: 600, +draggingRowIndex: -1, +draggingRowNode: null, +placeholderRowIndex: -1, +dragToScrollThreshold: .1, +prevScrollTop: 0, +autoScrollTimeoutMS: 20, +autoScrollTimeout: null, +autoscrollPageY: 0, +pinnedReorderMode: !1, +initialPinPosition: -1, +itemMoved: !1, +currentPageNumber: -1, +completeReorderTimeout: null, +swipeIndex: null, +swipeDirection: null, +persistentItemVisible: !1, +persistentItemOrigin: null, +swipeComplete: !1, +completeSwipeTimeout: null, +completeSwipeDelayMS: 500, +normalSwipeSpeedMS: 200, +fastSwipeSpeedMS: 100, +percentageDraggedThreshold: .2, +importProps: function(e) { +e && e.reorderable && (this.touch = !0), this.inherited(arguments); +}, +create: function() { +this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); +}, +initComponents: function() { +this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); +}, +createReorderTools: function() { +this.createComponent({ +name: "reorderContainer", +classes: "enyo-list-reorder-container", +ondown: "sendToStrategy", +ondrag: "sendToStrategy", +ondragstart: "sendToStrategy", +ondragfinish: "sendToStrategy", +onflick: "sendToStrategy" +}); +}, +createStrategy: function() { +this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); +}, +createSwipeableComponents: function() { +for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { +owner: this.owner +}); +}, +rendered: function() { +this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); +}, +resizeHandler: function() { +this.inherited(arguments), this.refresh(); +}, +bottomUpChanged: function() { +this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); +}, +noSelectChanged: function() { +this.$.generator.setNoSelect(this.noSelect); +}, +multiSelectChanged: function() { +this.$.generator.setMultiSelect(this.multiSelect); +}, +toggleSelectedChanged: function() { +this.$.generator.setToggleSelected(this.toggleSelected); +}, +countChanged: function() { +this.hasNode() && this.updateMetrics(); +}, +sendToStrategy: function(e, t) { +this.$.strategy.dispatchEvent("on" + t.type, t, e); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +holdpulse: function(e, t) { +if (!this.getReorderable() || this.isReordering()) return; +if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; +}, +dragstart: function(e, t) { +if (this.isReordering()) return !0; +if (this.isSwipeable()) return this.swipeDragStart(e, t); +}, +drag: function(e, t) { +if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; +if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; +}, +dragfinish: function(e, t) { +this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); +}, +up: function(e, t) { +this.isReordering() && this.finishReordering(e, t); +}, +generatePage: function(e, t) { +this.page = e; +var n = this.rowsPerPage * this.page; +this.$.generator.setRowOffset(n); +var r = Math.min(this.count - n, this.rowsPerPage); +this.$.generator.setCount(r); +var i = this.$.generator.generateChildHtml(); +t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); +var s = t.getBounds().height; +!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); +if (!this.fixedHeight) { +var o = this.getPageHeight(e); +this.pageHeights[e] = s, this.portSize += s - o; +} +}, +pageForRow: function(e) { +return Math.floor(e / this.rowsPerPage); +}, +preserveDraggingRowNode: function(e) { +this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); +}, +update: function(e) { +var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; +this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); +}, +getPageRowHeights: function(e) { +var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); +for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { +height: s.height, +width: s.width +}); +return t; +}, +updateRowBounds: function(e) { +this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); +}, +updateRowBoundsAtIndex: function(e, t, n) { +var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); +t[e].height = i.height, t[e].width = i.width; +}, +updateForPosition: function(e) { +this.update(this.calcPos(e)); +}, +calcPos: function(e) { +return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; +}, +adjustBottomPage: function() { +var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; +this.positionPage(e.pageNo, e); +}, +adjustPortSize: function() { +this.scrollerHeight = this.getBounds().height; +var e = Math.max(this.scrollerHeight, this.portSize); +this.$.port.applyStyle("height", e + "px"); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e); +t.applyStyle(this.pageBound, n + "px"); +}, +pageToPosition: function(e) { +var t = 0, n = e; +while (n > 0) n--, t += this.getPageHeight(n); +return t; +}, +positionToPageInfo: function(e) { +var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; +while (n >= 0) t++, r = this.getPageHeight(t), n -= r; +return t = Math.max(t, 0), { +no: t, +height: r, +pos: n + r, +startRow: t * this.rowsPerPage, +endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) +}; +}, +isPageInRange: function(e) { +return e == Math.max(0, Math.min(this.pageCount - 1, e)); +}, +getPageHeight: function(e) { +var t = this.pageHeights[e]; +if (!t) { +var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); +t = this.defaultPageHeight * (r / this.rowsPerPage); +} +return Math.max(1, t); +}, +invalidatePages: function() { +this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); +}, +invalidateMetrics: function() { +this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); +}, +scroll: function(e, t) { +var n = this.inherited(arguments), r = this.getScrollTop(); +return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); +}, +setScrollTop: function(e) { +this.update(e), this.inherited(arguments), this.twiddle(); +}, +getScrollPosition: function() { +return this.calcPos(this.getScrollTop()); +}, +setScrollPosition: function(e) { +this.setScrollTop(this.calcPos(e)); +}, +scrollToBottom: function() { +this.update(this.getScrollBounds().maxTop), this.inherited(arguments); +}, +scrollToRow: function(e) { +var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); +this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); +if (t == this.p0 || t == this.p1) { +var i = this.$.generator.fetchRowNode(e); +if (i) { +var s = i.offsetTop; +this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); +var o = this.getScrollPosition() + s; +this.setScrollPosition(o); +} +} +}, +scrollToStart: function() { +this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); +}, +scrollToEnd: function() { +this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); +}, +refresh: function() { +this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); +}, +reset: function() { +this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); +}, +getSelection: function() { +return this.$.generator.getSelection(); +}, +select: function(e, t) { +return this.getSelection().select(e, t); +}, +deselect: function(e) { +return this.getSelection().deselect(e); +}, +isSelected: function(e) { +return this.$.generator.isSelected(e); +}, +renderRow: function(e) { +this.$.generator.renderRow(e); +}, +rowRendered: function(e, t) { +this.updateRowBounds(t.rowIndex); +}, +prepareRow: function(e) { +this.$.generator.prepareRow(e); +}, +lockRow: function() { +this.$.generator.lockRow(); +}, +performOnRow: function(e, t, n) { +this.$.generator.performOnRow(e, t, n); +}, +animateFinish: function(e) { +return this.twiddle(), !0; +}, +twiddle: function() { +var e = this.getStrategy(); +enyo.call(e, "twiddle"); +}, +pageForPageNumber: function(e, t) { +return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; +}, +shouldStartReordering: function(e, t) { +return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; +}, +startReordering: function(e) { +this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); +}, +buildReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +styleReorderContainer: function(e) { +this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); +}, +appendNodeToReorderContainer: function(e) { +this.$.reorderContainer.createComponent({ +allowHtml: !0, +content: e.innerHTML +}).render(); +}, +centerReorderContainerOnPointer: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; +this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); +}, +positionReorderContainer: function(e, t) { +this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); +}, +setPositionReorderContainerTimeout: function() { +this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { +this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); +}), 100); +}, +clearPositionReorderContainerTimeout: function() { +this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); +}, +shouldDoReorderDrag: function() { +return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; +}, +reorderDrag: function(e) { +this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); +}, +updatePlaceholderPosition: function(e) { +var t = this.getRowIndexFromCoordinate(e); +t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); +}, +positionReorderNode: function(e) { +var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; +r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); +}, +checkForAutoScroll: function(e) { +var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; +this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); +}, +stopAutoScrolling: function() { +this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); +}, +startAutoScrolling: function() { +this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); +}, +autoScroll: function() { +this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ +ddx: 0, +ddy: 0 +}), this.updatePlaceholderPosition(this.autoscrollPageY); +}, +movePlaceholderToIndex: function(e) { +var t, n; +if (e < 0) return; +e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); +var r = this.pageForRow(e); +r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; +}, +finishReordering: function(e, t) { +if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; +return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; +}, +moveReorderedContainerToDroppedPosition: function() { +var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); +this.positionReorderContainer(n, t); +}, +completeFinishReordering: function(e) { +this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); +if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { +this.beginPinnedReorder(e); +return; +} +this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); +}, +beginPinnedReorder: function(e) { +this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { +index: this.draggingRowIndex +})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; +}, +emptyAndHideReorderContainer: function() { +this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); +}, +buildPinnedReorderContainer: function() { +this.$.reorderContainer.destroyClientControls(); +for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { +owner: this.owner +}); +this.$.reorderContainer.render(); +}, +reorderRows: function(e) { +this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); +}, +makeReorderEvent: function(e) { +return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; +}, +positionReorderedNode: function() { +if (!this.removedInitialPage) { +var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); +e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; +if (this.currentPageNumber != this.initialPageNumber) { +var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); +this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); +} +} +}, +updateListIndices: function() { +if (this.shouldDoRefresh()) { +this.refresh(), this.correctPageHeights(); +return; +} +var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; +if (n === 1) { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); +for (i = t - 1, s = t; i >= e; i--) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); +} +r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); +} else { +r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); +for (i = e + 1, s = e; i <= t; i++) { +r = this.$.generator.fetchRowNode(i); +if (!r) continue; +o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); +} +} +}, +shouldDoRefresh: function() { +return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; +}, +getNodeStyle: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) return; +var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); +return { +h: r.height, +w: r.width, +left: n.left, +top: n.top +}; +}, +getRelativeOffset: function(e, t) { +var n = { +top: 0, +left: 0 +}; +if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); +return n; +}, +replaceNodeWithPlaceholder: function(e) { +var t = this.$.generator.fetchRowNode(e); +if (!t) { +enyo.log("No node - " + e); +return; +} +this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); +var n = this.pageForPageNumber(this.currentPageNumber); +n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); +}, +createPlaceholderNode: function(e) { +var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); +return t.style.height = n.height + "px", t.style.width = n.width + "px", t; +}, +removePlaceholderNode: function() { +this.removeNode(this.placeholderNode), this.placeholderNode = null; +}, +removeDraggingRowNode: function() { +this.draggingRowNode = null; +var e = this.$.holdingarea.hasNode(); +e.innerHTML = ""; +}, +removeNode: function(e) { +if (!e || !e.parentNode) return; +e.parentNode.removeChild(e); +}, +updatePageHeight: function(e) { +if (e < 0) return; +var t = this.pageForPageNumber(e, !0); +if (t) { +var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); +this.pageHeights[e] = r, this.portSize += r - n; +} +}, +updatePagePositions: function(e) { +this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); +}, +correctPageHeights: function() { +this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); +}, +hideNode: function(e) { +return e.style.display = "none", e; +}, +showNode: function(e) { +return e.style.display = "block", e; +}, +dropPinnedRow: function(e) { +this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); +return; +}, +cancelPinnedMode: function(e) { +this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); +}, +getRowIndexFromCoordinate: function(e) { +var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; +if (t < 0) return -1; +var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; +if (!r) return this.count; +var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; +for (var u = n.startRow; u <= n.endRow; ++u) { +if (u === this.placeholderRowIndex) { +o += s; +if (o >= i) return -1; +} +if (u !== this.draggingRowIndex) { +o += r[u].height; +if (o >= i) return u; +} +} +return u; +}, +getIndexPosition: function(e) { +return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); +}, +setItemPosition: function(e, t) { +var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; +e.addStyles(i); +}, +setItemBounds: function(e, t) { +var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; +e.addStyles(r); +}, +reorderScroll: function(e, t) { +this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); +}, +hideReorderingRow: function() { +var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); +e && (this.hiddenNode = this.hideNode(e)); +}, +isReordering: function() { +return this.draggingRowIndex > -1; +}, +isSwiping: function() { +return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; +}, +swipeDragStart: function(e, t) { +return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); +}, +swipeDrag: function(e, t) { +return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; +}, +swipeDragFinish: function(e, t) { +if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { +if (!this.isSwiping()) return !1; +var n = this.calcPercentageDragged(this.draggedXDistance); +n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); +} +return this.preventDragPropagation; +}, +isSwipeable: function() { +return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; +}, +positionSwipeableContainer: function(e, t) { +var n = this.$.generator.fetchRowNode(e); +if (!n) return; +var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; +this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); +}, +calcNewDragPosition: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; +return s; +}, +dragSwipeableComponents: function(e) { +this.$.swipeableComponents.applyStyle("left", e + "px"); +}, +startSwipe: function(e) { +e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); +}, +dragPersistentItem: function(e) { +var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); +this.$.swipeableComponents.applyStyle("left", n + "px"); +}, +dragFinishPersistentItem: function(e) { +var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; +this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); +}, +setPersistentItemOrigin: function(e) { +this.persistentItemOrigin = e == 1 ? "left" : "right"; +}, +calcPercentageDragged: function(e) { +return Math.abs(e / this.$.swipeableComponents.getBounds().width); +}, +swipe: function(e) { +this.swipeComplete = !0, this.animateSwipe(0, e); +}, +backOutSwipe: function(e) { +var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; +this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; +}, +bounceItem: function(e) { +var t = this.$.swipeableComponents.getBounds(); +t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); +}, +slideAwayItem: function() { +var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; +this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +clearSwipeables: function() { +this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); +}, +completeSwipe: function(e) { +this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ +index: this.swipeIndex, +xDirection: this.swipeDirection +})), this.swipeIndex = null, this.swipeDirection = null; +}, +animateSwipe: function(e, t) { +var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; +this.stopAnimateSwipe(); +var u = enyo.bind(this, function() { +var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); +i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { +this.completeSwipe(); +}), this.completeSwipeDelayMS)); +}); +this.job = enyo.requestAnimationFrame(u); +}, +stopAnimateSwipe: function() { +this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); +} +}); + +// PulldownList.js + +enyo.kind({ +name: "enyo.PulldownList", +kind: "List", +touch: !0, +pully: null, +pulldownTools: [ { +name: "pulldown", +classes: "enyo-list-pulldown", +components: [ { +name: "puller", +kind: "Puller" +} ] +} ], +events: { +onPullStart: "", +onPullCancel: "", +onPull: "", +onPullRelease: "", +onPullComplete: "" +}, +handlers: { +onScrollStart: "scrollStartHandler", +onScrollStop: "scrollStopHandler", +ondragfinish: "dragfinish" +}, +pullingMessage: "Pull down to refresh...", +pulledMessage: "Release to refresh...", +loadingMessage: "Loading...", +pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", +pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", +loadingIconClass: "", +create: function() { +var e = { +kind: "Puller", +showing: !1, +text: this.loadingMessage, +iconClass: this.loadingIconClass, +onCreate: "setPully" +}; +this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); +}, +initComponents: function() { +this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); +}, +resetStrategyKind: function() { +return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; +}, +setPully: function(e, t) { +this.pully = t.originator; +}, +scrollStartHandler: function() { +this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; +}, +scroll: function(e, t) { +var n = this.inherited(arguments); +this.completingPull && this.pully.setShowing(!1); +var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); +return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; +}, +scrollStopHandler: function() { +this.completingPull && (this.completingPull = !1, this.doPullComplete()); +}, +dragfinish: function() { +if (this.firedPull) { +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); +} +}, +completePull: function() { +this.completingPull = !0; +var e = this.getStrategy().$.scrollMath || this.getStrategy(); +e.setScrollY(this.pullHeight), e.start(); +}, +pullStart: function() { +this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); +}, +pull: function() { +this.setPulled(), this.doPull(); +}, +pullCancel: function() { +this.setPulling(), this.doPullCancel(); +}, +pullRelease: function() { +this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); +}, +setPulling: function() { +this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); +}, +setPulled: function() { +this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); +} +}), enyo.kind({ +name: "enyo.Puller", +classes: "enyo-puller", +published: { +text: "", +iconClass: "" +}, +events: { +onCreate: "" +}, +components: [ { +name: "icon" +}, { +name: "text", +tag: "span", +classes: "enyo-puller-text" +} ], +create: function() { +this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); +}, +textChanged: function() { +this.$.text.setContent(this.text); +}, +iconClassChanged: function() { +this.$.icon.setClasses(this.iconClass); +} +}); + +// AroundList.js + +enyo.kind({ +name: "enyo.AroundList", +kind: "enyo.List", +listTools: [ { +name: "port", +classes: "enyo-list-port enyo-border-box", +components: [ { +name: "aboveClient" +}, { +name: "generator", +kind: "FlyweightRepeater", +canGenerate: !1, +components: [ { +tag: null, +name: "client" +} ] +}, { +name: "holdingarea", +allowHtml: !0, +classes: "enyo-list-holdingarea" +}, { +name: "page0", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "page1", +allowHtml: !0, +classes: "enyo-list-page" +}, { +name: "belowClient" +}, { +name: "placeholder" +}, { +name: "swipeableComponents", +style: "position:absolute; display:block; top:-1000px; left:0px;" +} ] +} ], +aboveComponents: null, +initComponents: function() { +this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { +owner: this.owner +}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { +owner: this.owner +}); +}, +updateMetrics: function() { +this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; +for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); +this.adjustPortSize(); +}, +positionPage: function(e, t) { +t.pageNo = e; +var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; +n += r, t.applyStyle(this.pageBound, n + "px"); +}, +scrollToContentStart: function() { +var e = this.bottomUp ? this.belowHeight : this.aboveHeight; +this.setScrollPosition(e); +} +}); + +// Slideable.js + +enyo.kind({ +name: "enyo.Slideable", +kind: "Control", +published: { +axis: "h", +value: 0, +unit: "px", +min: 0, +max: 0, +accelerated: "auto", +overMoving: !0, +draggable: !0 +}, +events: { +onAnimateFinish: "", +onChange: "" +}, +preventDragPropagation: !1, +tools: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorComplete" +} ], +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +kDragScalar: 1, +dragEventProp: "dx", +unitModifier: !1, +canTransform: !1, +create: function() { +this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); +}, +initComponents: function() { +this.createComponents(this.tools), this.inherited(arguments); +}, +rendered: function() { +this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); +}, +resizeHandler: function() { +this.inherited(arguments), this.updateDragScalar(); +}, +canModifyUnit: function() { +if (!this.canTransform) { +var e = this.getInitialStyleValue(this.hasNode(), this.boundary); +e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); +} +}, +getInitialStyleValue: function(e, t) { +var n = enyo.dom.getComputedStyle(e); +return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; +}, +updateBounds: function(e, t) { +var n = {}; +n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); +}, +updateDragScalar: function() { +if (this.unit == "%") { +var e = this.getBounds()[this.dimension]; +this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); +} +}, +transformChanged: function() { +this.canTransform = enyo.dom.canTransform(); +}, +acceleratedChanged: function() { +enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); +}, +axisChanged: function() { +var e = this.axis == "h"; +this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; +}, +setInlineStyles: function(e, t) { +var n = {}; +this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); +}, +valueChanged: function(e) { +var t = this.value; +this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); +}, +getAnimator: function() { +return this.$.animator; +}, +isAtMin: function() { +return this.value <= this.calcMin(); +}, +isAtMax: function() { +return this.value >= this.calcMax(); +}, +calcMin: function() { +return this.min; +}, +calcMax: function() { +return this.max; +}, +clampValue: function(e) { +var t = this.calcMin(), n = this.calcMax(); +return Math.max(t, Math.min(e, n)); +}, +dampValue: function(e) { +return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); +}, +dampBound: function(e, t, n) { +var r = e; +return r * n < t * n && (r = t + (r - t) / 4), r; +}, +percentToPixels: function(e, t) { +return Math.floor(t / 100 * e); +}, +pixelsToPercent: function(e) { +var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; +return e / t * 100; +}, +shouldDrag: function(e) { +return this.draggable && e[this.shouldDragProp]; +}, +isOob: function(e) { +return e > this.calcMax() || e < this.calcMin(); +}, +dragstart: function(e, t) { +if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; +}, +drag: function(e, t) { +if (this.dragging) { +t.preventDefault(); +var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; +return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; +} +}, +dragfinish: function(e, t) { +if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; +}, +completeDrag: function(e) { +this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); +}, +isAnimating: function() { +return this.$.animator.isAnimating(); +}, +play: function(e, t) { +this.$.animator.play({ +startValue: e, +endValue: t, +node: this.hasNode() +}); +}, +animateTo: function(e) { +this.play(this.value, e); +}, +animateToMin: function() { +this.animateTo(this.calcMin()); +}, +animateToMax: function() { +this.animateTo(this.calcMax()); +}, +animateToMinMax: function(e) { +e ? this.animateToMin() : this.animateToMax(); +}, +animatorStep: function(e) { +return this.setValue(e.value), !0; +}, +animatorComplete: function(e) { +return this.doAnimateFinish(e), !0; +}, +toggleMinMax: function() { +this.animateToMinMax(!this.isAtMin()); +} +}); + +// Arranger.js + +enyo.kind({ +name: "enyo.Arranger", +kind: "Layout", +layoutClass: "enyo-arranger", +accelerated: "auto", +dragProp: "ddx", +dragDirectionProp: "xDirection", +canDragProp: "horizontal", +incrementalPoints: !1, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n._arranger = null; +this.inherited(arguments); +}, +arrange: function(e, t) {}, +size: function() {}, +start: function() { +var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; +if (this.incrementalPoints) { +var r = Math.abs(t - e) - 2, i = e; +while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; +} +n.push(this.container.toIndex); +}, +finish: function() {}, +calcArrangementDifference: function(e, t, n, r) {}, +canDragEvent: function(e) { +return e[this.canDragProp]; +}, +calcDragDirection: function(e) { +return e[this.dragDirectionProp]; +}, +calcDrag: function(e) { +return e[this.dragProp]; +}, +drag: function(e, t, n, r, i) { +var s = this.measureArrangementDelta(-e, t, n, r, i); +return s; +}, +measureArrangementDelta: function(e, t, n, r, i) { +var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; +return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; +}, +_arrange: function(e) { +this.containerBounds || this.reflow(); +var t = this.getOrderedControls(e); +this.arrange(t, e); +}, +arrangeControl: function(e, t) { +e._arranger = enyo.mixin(e._arranger || {}, t); +}, +flow: function() { +this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { +enyo.dom.accelerate(n, this.accelerated); +if (enyo.platform.safari) { +var r = n.children; +for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); +} +} +}, +reflow: function() { +var e = this.container.hasNode(); +this.containerBounds = e ? { +width: e.clientWidth, +height: e.clientHeight +} : {}, this.size(); +}, +flowArrangement: function() { +var e = this.container.arrangement; +if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); +}, +flowControl: function(e, t) { +enyo.Arranger.positionControl(e, t); +var n = t.opacity; +n != null && enyo.Arranger.opacifyControl(e, n); +}, +getOrderedControls: function(e) { +var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; +for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); +return this.controlsIndex = t, i; +}, +statics: { +positionControl: function(e, t, n) { +var r = n || "px"; +if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { +var i = t.left, s = t.top; +i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { +translateX: i || null, +translateY: s || null +}); +} else e.setBounds(t, n); +}, +opacifyControl: function(e, t) { +var n = t; +n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); +} +} +}); + +// CardArranger.js + +enyo.kind({ +name: "enyo.CardArranger", +kind: "Arranger", +layoutClass: "enyo-arranger enyo-arranger-fit", +calcArrangementDifference: function(e, t, n, r) { +return this.containerBounds.width; +}, +arrange: function(e, t) { +for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { +opacity: s +}); +}, +start: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); +this.inherited(arguments); +} +}); + +// CardSlideInArranger.js + +enyo.kind({ +name: "enyo.CardSlideInArranger", +kind: "CardArranger", +start: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) { +var r = n.showing; +n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); +} +var i = this.container.fromIndex; +t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; +}, +finish: function() { +this.inherited(arguments); +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); +}, +arrange: function(e, t) { +var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; +for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { +left: l +}); +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null +}); +this.inherited(arguments); +} +}); + +// CarouselArranger.js + +enyo.kind({ +name: "enyo.CarouselArranger", +kind: "Arranger", +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; +n.height -= t.top + t.bottom, n.width -= t.left + t.right; +var a; +for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); +if (a) { +var f = n.width - s; +a.width = f >= 0 ? f : a.width; +} +for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ +top: t.top, +bottom: t.bottom, +width: u.fit ? u.width : null +}); +}, +arrange: function(e, t) { +this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); +}, +arrangeNoWrap: function(e, t) { +var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; +for (n = u, i = 0; s = o[n]; n++) { +i += s.width + s.marginWidth; +if (i > a) break; +} +var f = a - i, l = 0; +if (f > 0) { +var c = u; +for (n = u - 1, r = 0; s = o[n]; n--) { +r += s.width + s.marginWidth; +if (f - r <= 0) { +l = f - r, u = n; +break; +} +} +} +var h, p; +for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { +left: -h +}) : (this.arrangeControl(s, { +left: Math.floor(p) +}), p += h); +}, +arrangeWrap: function(e, t) { +for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { +left: r +}), r += s.width + s.marginWidth; +}, +calcArrangementDifference: function(e, t, n, r) { +var i = Math.abs(e % this.c$.length); +return t[i].left - r[i].left; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// CollapsingArranger.js + +enyo.kind({ +name: "enyo.CollapsingArranger", +kind: "CarouselArranger", +peekWidth: 0, +size: function() { +this.clearLastSize(), this.inherited(arguments); +}, +clearLastSize: function() { +for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); +}, +constructor: function() { +this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; +}, +arrange: function(e, t) { +var n = this.container.getPanels(); +for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { +left: i + u * this.peekWidth +}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { +left: i +}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { +left: i - t +}); +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels().length - 1; +return Math.abs(r[i].left - t[i].left); +}, +flowControl: function(e, t) { +this.inherited(arguments); +if (this.container.realtimeFit) { +var n = this.container.getPanels(), r = n.length - 1, i = n[r]; +e == i && this.fitControl(e, t.left); +} +}, +finish: function() { +this.inherited(arguments); +if (!this.container.realtimeFit && this.containerBounds) { +var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; +this.fitControl(r, t[n].left); +} +}, +fitControl: function(e, t) { +e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); +} +}); + +// DockRightArranger.js + +enyo.kind({ +name: "enyo.DockRightArranger", +kind: "Arranger", +basePanel: !1, +overlap: 0, +layoutWidth: 0, +constructor: function() { +this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; +n.width -= t.left + t.right; +var o = n.width, u = e.length; +this.container.transitionPositions = {}; +for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; +for (r = 0; s = e[r]; r++) { +r === 0 && this.container.basePanel && s.setBounds({ +width: o +}), s.setBounds({ +top: t.top, +bottom: t.bottom +}); +for (j = 0; s = e[j]; j++) { +var a; +if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { +if (r !== j) break; +var f = o > this.layoutWidth ? this.overlap : 0; +a = o - e[r].width + f; +} +this.container.transitionPositions[r + "." + j] = a; +} +if (j < u) { +var l = !1; +for (k = r + 1; k < u; k++) { +var f = 0; +if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { +f = e[r].width - this.overlap; +for (i = r; i < k; i++) { +var c = f + e[i + 1].width - this.overlap; +if (!(c < o)) { +f = o; +break; +} +f = c; +} +f = o - f; +} +this.container.transitionPositions[r + "." + k] = f; +} +} +} +}, +arrange: function(e, t) { +var n, r, i = this.container.getPanels(), s = this.container.clamp(t); +for (n = 0; r = i[n]; n++) { +var o = this.container.transitionPositions[n + "." + s]; +this.arrangeControl(r, { +left: o +}); +} +}, +calcArrangementDifference: function(e, t, n, r) { +var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; +return s; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// OtherArrangers.js + +enyo.kind({ +name: "enyo.LeftRightArranger", +kind: "Arranger", +margin: 40, +axisSize: "width", +offAxisSize: "height", +axisPosition: "left", +constructor: function() { +this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; +}, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; +for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); +}, +start: function() { +this.inherited(arguments); +var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); +for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); +}, +arrange: function(e, t) { +var n, r, i, s; +if (this.container.getPanels().length == 1) { +s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); +return; +} +var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; +for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; +}, +calcArrangementDifference: function(e, t, n, r) { +if (this.container.getPanels().length == 1) return 0; +var i = Math.abs(e % this.c$.length); +return t[i][this.axisPosition] - r[i][this.axisPosition]; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.TopBottomArranger", +kind: "LeftRightArranger", +dragProp: "ddy", +dragDirectionProp: "yDirection", +canDragProp: "vertical", +axisSize: "height", +offAxisSize: "width", +axisPosition: "top" +}), enyo.kind({ +name: "enyo.SpiralArranger", +kind: "Arranger", +incrementalPoints: !0, +inc: 20, +size: function() { +var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; +for (var i = 0, s; s = e[i]; i++) s.setBounds({ +width: n, +height: r +}); +}, +arrange: function(e, t) { +var n = this.inc; +for (var r = 0, i = e.length, s; s = e[r]; r++) { +var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; +this.arrangeControl(s, { +left: o, +top: u +}); +} +}, +start: function() { +this.inherited(arguments); +var e = this.getOrderedControls(this.container.toIndex); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.controlWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}), enyo.kind({ +name: "enyo.GridArranger", +kind: "Arranger", +incrementalPoints: !0, +colWidth: 100, +colHeight: 100, +size: function() { +var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; +for (var r = 0, i; i = e[r]; r++) i.setBounds({ +width: t, +height: n +}); +}, +arrange: function(e, t) { +var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; +for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { +left: n * a, +top: r * o +}); +}, +flowControl: function(e, t) { +this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); +}, +calcArrangementDifference: function(e, t, n, r) { +return this.colWidth; +}, +destroy: function() { +var e = this.container.getPanels(); +for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { +left: null, +top: null +}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); +this.inherited(arguments); +} +}); + +// Panels.js + +enyo.kind({ +name: "enyo.Panels", +classes: "enyo-panels", +published: { +index: 0, +draggable: !0, +animate: !0, +wrap: !1, +arrangerKind: "CardArranger", +narrowFit: !0 +}, +events: { +onTransitionStart: "", +onTransitionFinish: "" +}, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +onscroll: "domScroll" +}, +tools: [ { +kind: "Animator", +onStep: "step", +onEnd: "completed" +} ], +fraction: 0, +create: function() { +this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); +}, +rendered: function() { +this.inherited(arguments), enyo.makeBubble(this, "scroll"); +}, +domScroll: function(e, t) { +this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); +}, +initComponents: function() { +this.createChrome(this.tools), this.inherited(arguments); +}, +arrangerKindChanged: function() { +this.setLayoutKind(this.arrangerKind); +}, +narrowFitChanged: function() { +this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); +}, +destroy: function() { +this.destroying = !0, this.inherited(arguments); +}, +removeControl: function(e) { +this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); +}, +isPanel: function() { +return !0; +}, +flow: function() { +this.arrangements = [], this.inherited(arguments); +}, +reflow: function() { +this.arrangements = [], this.inherited(arguments), this.refresh(); +}, +getPanels: function() { +var e = this.controlParent || this; +return e.children; +}, +getActive: function() { +var e = this.getPanels(), t = this.index % e.length; +return t < 0 && (t += e.length), e[t]; +}, +getAnimator: function() { +return this.$.animator; +}, +setIndex: function(e) { +this.setPropertyValue("index", e, "indexChanged"); +}, +setIndexDirect: function(e) { +this.setIndex(e), this.completed(); +}, +previous: function() { +this.setIndex(this.index - 1); +}, +next: function() { +this.setIndex(this.index + 1); +}, +clamp: function(e) { +var t = this.getPanels().length - 1; +return this.wrap ? e : Math.max(0, Math.min(e, t)); +}, +indexChanged: function(e) { +this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ +startValue: this.fraction +})) : this.refresh())); +}, +step: function(e) { +this.fraction = e.value, this.stepTransition(); +}, +completed: function() { +this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +dragstart: function(e, t) { +if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; +}, +drag: function(e, t) { +this.dragging && (t.preventDefault(), this.dragTransition(t)); +}, +dragfinish: function(e, t) { +this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); +}, +dragstartTransition: function(e) { +if (!this.$.animator.isAnimating()) { +var t = this.fromIndex = this.index; +this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); +} else this.verifyDragTransition(e); +this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); +}, +dragTransition: function(e) { +var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; +a, this.fraction += u; +var f = this.fraction; +if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; +this.stepTransition(); +}, +dragfinishTransition: function(e) { +this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); +}, +verifyDragTransition: function(e) { +var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); +if (t > 0) { +var i = n; +n = r, r = i; +} +n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; +}, +refresh: function() { +this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); +}, +startTransition: function() { +this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); +}, +finishTransition: function() { +this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); +}, +fireTransitionStart: function() { +var e = this.startTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { +fromIndex: this.fromIndex, +toIndex: this.toIndex +}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); +}, +fireTransitionFinish: function() { +var e = this.finishTransitionInfo; +this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { +fromIndex: this.lastIndex, +toIndex: this.index +}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; +}, +stepTransition: function() { +if (this.hasNode()) { +var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); +t -= n; +var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); +this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); +} +}, +fetchArrangement: function(e) { +return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; +}, +readArrangement: function(e) { +var t = []; +for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); +return t; +}, +statics: { +isScreenNarrow: function() { +return enyo.dom.getWindowWidth() <= 800; +}, +lerp: function(e, t, n) { +var r = []; +for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); +return r; +}, +lerpObject: function(e, t, n) { +var r = enyo.clone(e), i, s; +if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); +return r; +} +} +}); + +// Node.js + +enyo.kind({ +name: "enyo.Node", +published: { +expandable: !1, +expanded: !1, +icon: "", +onlyIconExpands: !1, +selected: !1 +}, +style: "padding: 0 0 0 16px;", +content: "Node", +defaultKind: "Node", +classes: "enyo-node", +components: [ { +name: "icon", +kind: "Image", +showing: !1 +}, { +kind: "Control", +name: "caption", +Xtag: "span", +style: "display: inline-block; padding: 4px;", +allowHtml: !0 +}, { +kind: "Control", +name: "extra", +tag: "span", +allowHtml: !0 +} ], +childClient: [ { +kind: "Control", +name: "box", +classes: "enyo-node-box", +Xstyle: "border: 1px solid orange;", +components: [ { +kind: "Control", +name: "client", +classes: "enyo-node-client", +Xstyle: "border: 1px solid lightblue;" +} ] +} ], +handlers: { +ondblclick: "dblclick" +}, +events: { +onNodeTap: "nodeTap", +onNodeDblClick: "nodeDblClick", +onExpand: "nodeExpand", +onDestroyed: "nodeDestroyed" +}, +create: function() { +this.inherited(arguments), this.selectedChanged(), this.iconChanged(); +}, +destroy: function() { +this.doDestroyed(), this.inherited(arguments); +}, +initComponents: function() { +this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); +}, +contentChanged: function() { +this.$.caption.setContent(this.content); +}, +iconChanged: function() { +this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); +}, +selectedChanged: function() { +this.addRemoveClass("enyo-selected", this.selected); +}, +rendered: function() { +this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); +}, +addNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent(n); +this.$.client.render(); +}, +addTextNodes: function(e) { +this.destroyClientControls(); +for (var t = 0, n; n = e[t]; t++) this.createComponent({ +content: n +}); +this.$.client.render(); +}, +tap: function(e, t) { +return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; +}, +dblclick: function(e, t) { +return this.doNodeDblClick(), !0; +}, +toggleExpanded: function() { +this.setExpanded(!this.expanded); +}, +quickCollapse: function() { +this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); +var e = this.$.client.getBounds().height; +this.$.client.setBounds({ +top: -e +}); +}, +_expand: function() { +this.addClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), this.$.client.setBounds({ +top: 0 +}), setTimeout(enyo.bind(this, function() { +this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); +}), 225); +}, +_collapse: function() { +this.removeClass("enyo-animate"); +var e = this.$.client.getBounds().height; +this.$.box.setBounds({ +height: e +}), setTimeout(enyo.bind(this, function() { +this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ +top: -e +}); +}), 25); +}, +expandedChanged: function(e) { +if (!this.expandable) this.expanded = !1; else { +var t = { +expanded: this.expanded +}; +this.doExpand(t), t.wait || this.effectExpanded(); +} +}, +effectExpanded: function() { +this.$.client && (this.expanded ? this._expand() : this._collapse()); +} +}); + +// ImageViewPin.js + +enyo.kind({ +name: "enyo.ImageViewPin", +kind: "enyo.Control", +published: { +highlightAnchorPoint: !1, +anchor: { +top: 0, +left: 0 +}, +position: { +top: 0, +left: 0 +} +}, +style: "position:absolute;z-index:1000;width:0px;height:0px;", +handlers: { +onPositionPin: "reAnchor" +}, +create: function() { +this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); +}, +styleClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); +}, +positionClientControls: function() { +var e = this.getClientControls(); +for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); +}, +highlightAnchorPointChanged: function() { +this.addRemoveClass("pinDebug", this.highlightAnchorPoint); +}, +anchorChanged: function() { +var e = null, t = null; +for (t in this.anchor) { +e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); +if (!e) continue; +this.anchor[t + "Coords"] = { +value: e[1], +units: e[2] || "px" +}; +} +}, +reAnchor: function(e, t) { +var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; +this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); +} +}); + +// ImageView.js + +enyo.kind({ +name: "enyo.ImageView", +kind: enyo.Scroller, +touchOverscroll: !1, +thumb: !1, +animate: !0, +verticalDragPropagation: !0, +horizontalDragPropagation: !0, +published: { +scale: "auto", +disableZoom: !1, +src: undefined +}, +events: { +onZoom: "" +}, +touch: !0, +preventDragPropagation: !1, +handlers: { +ondragstart: "dragPropagation" +}, +components: [ { +name: "animator", +kind: "Animator", +onStep: "zoomAnimationStep", +onEnd: "zoomAnimationEnd" +}, { +name: "viewport", +style: "overflow:hidden;min-height:100%;min-width:100%;", +classes: "enyo-fit", +ongesturechange: "gestureTransform", +ongestureend: "saveState", +ontap: "singleTap", +ondblclick: "doubleClick", +onmousewheel: "mousewheel", +components: [ { +kind: "Image", +ondown: "down" +} ] +} ], +create: function() { +this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); +}, +down: function(e, t) { +t.preventDefault(); +}, +dragPropagation: function(e, t) { +var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; +return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); +}, +mousewheel: function(e, t) { +t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; +var n = (this.maxScale - this.minScale) / 10, r = this.scale; +if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); +return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; +}, +srcChanged: function() { +this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); +}, +imageLoaded: function(e) { +this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); +}, +resizeHandler: function() { +this.inherited(arguments), this.$.image.src && this.scaleChanged(); +}, +scaleChanged: function() { +var e = this.hasNode(); +if (e) { +this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; +var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; +this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); +} +this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); +}, +imageError: function(e) { +enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); +}, +alignImage: function() { +if (this.fitAlignment && this.fitAlignment === "center") { +var e = this.getScrollBounds(); +this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); +} +}, +gestureTransform: function(e, t) { +this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); +}, +calcEventLocation: function(e) { +var t = { +x: 0, +y: 0 +}; +if (e && this.hasNode()) { +var n = this.node.getBoundingClientRect(); +t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); +} +return t; +}, +transformImage: function(e) { +this.tapped = !1; +var t = this.imageBounds || this.innerImageBounds(e); +this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px" +}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; +var n, r; +this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); +if (this.canTransform) { +var i = { +scale: e +}; +this.canAccelerate ? i = enyo.mixin({ +translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" +}, i) : i = enyo.mixin({ +translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" +}, i), enyo.dom.transform(this.$.image, i); +} else this.$.image.setBounds({ +width: this.imageBounds.width + "px", +height: this.imageBounds.height + "px", +left: this.imageBounds.left + "px", +top: this.imageBounds.top + "px" +}); +this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); +}, +limitScale: function(e) { +return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; +}, +innerImageBounds: function(e) { +var t = this.originalWidth * e, n = this.originalHeight * e, r = { +x: 0, +y: 0, +transX: 0, +transY: 0 +}; +return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { +left: r.x + r.transX, +top: r.y + r.transY, +width: t, +height: n, +x: r.x, +y: r.y +}; +}, +saveState: function(e, t) { +var n = this.scale; +this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ +scale: this.scale +}), this.ratioX = this.ratioY = null; +}, +doubleClick: function(e, t) { +enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); +}, +singleTap: function(e, t) { +setTimeout(enyo.bind(this, function() { +this.tapped = !1; +}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; +}, +smartZoom: function(e, t) { +var n = this.hasNode(), r = this.$.image.hasNode(); +if (n && r && this.hasNode() && !this.disableZoom) { +var i = this.scale; +this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); +if (this.animate) { +var s = { +x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, +y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height +}; +this.$.animator.play({ +duration: 350, +ratioLock: s, +baseScale: i, +deltaScale: this.scale - i +}); +} else this.transformImage(this.scale), this.doZoom({ +scale: this.scale +}); +} +}, +zoomAnimationStep: function(e, t) { +var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; +this.transformImage(n); +}, +zoomAnimationEnd: function(e, t) { +this.doZoom({ +scale: this.scale +}), this.$.animator.ratioLock = undefined; +}, +positionClientControls: function(e) { +this.waterfallDown("onPositionPin", { +scale: e, +bounds: this.imageBounds +}); +} +}); + +// ImageCarousel.js + +enyo.kind({ +name: "enyo.ImageCarousel", +kind: enyo.Panels, +arrangerKind: "enyo.CarouselArranger", +defaultScale: "auto", +disableZoom: !1, +lowMemory: !1, +published: { +images: [] +}, +handlers: { +onTransitionStart: "transitionStart", +onTransitionFinish: "transitionFinish" +}, +create: function() { +this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); +}, +initContainers: function() { +for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ +name: "container" + e, +style: "height:100%; width:100%;" +}), this.$["container" + e].render()); +for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); +this.imageCount = this.images.length; +}, +loadNearby: function() { +var e = this.getBufferRange(); +for (var t in e) this.loadImageView(e[t]); +}, +getBufferRange: function() { +var e = []; +if (this.layout.containerBounds) { +var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; +o = this.index - 1, u = 0, a = n.width * t; +while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; +o = this.index, u = 0, a = n.width * (t + 1); +while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; +} +return e; +}, +reflow: function() { +this.inherited(arguments), this.loadNearby(); +}, +loadImageView: function(e) { +return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ +name: "image" + e, +kind: "ImageView", +scale: this.defaultScale, +disableZoom: this.disableZoom, +src: this.images[e], +verticalDragPropagation: !1, +style: "height:100%; width:100%;" +}, { +owner: this +}), this.$["image" + e].render())), this.$["image" + e]; +}, +setImages: function(e) { +this.setPropertyValue("images", e, "imagesChanged"); +}, +imagesChanged: function() { +this.initContainers(), this.loadNearby(); +}, +indexChanged: function() { +this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); +}, +transitionStart: function(e, t) { +if (t.fromIndex == t.toIndex) return !0; +}, +transitionFinish: function(e, t) { +this.loadNearby(), this.lowMemory && this.cleanupMemory(); +}, +getActiveImage: function() { +return this.getImageByIndex(this.index); +}, +getImageByIndex: function(e) { +return this.$["image" + e] || this.loadImageView(e); +}, +cleanupMemory: function() { +var e = getBufferRange(); +for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); +} +}); + +// Icon.js + +enyo.kind({ +name: "onyx.Icon", +published: { +src: "", +disabled: !1 +}, +classes: "onyx-icon", +create: function() { +this.inherited(arguments), this.src && this.srcChanged(), this.disabledChanged(); +}, +disabledChanged: function() { +this.addRemoveClass("disabled", this.disabled); +}, +srcChanged: function() { +this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); +} +}); + +// Button.js + +enyo.kind({ +name: "onyx.Button", +kind: "enyo.Button", +classes: "onyx-button enyo-unselectable", +create: function() { +enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +} +}); + +// IconButton.js + +enyo.kind({ +name: "onyx.IconButton", +kind: "onyx.Icon", +published: { +active: !1 +}, +classes: "onyx-icon-button", +create: function() { +enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +}, +rendered: function() { +this.inherited(arguments), this.activeChanged(); +}, +tap: function() { +if (this.disabled) return !0; +this.setActive(!0); +}, +activeChanged: function() { +this.bubble("onActivate"); +} +}); + +// Checkbox.js + +enyo.kind({ +name: "onyx.Checkbox", +classes: "onyx-checkbox", +kind: enyo.Checkbox, +tag: "div", +handlers: { +onclick: "" +}, +tap: function(e, t) { +return this.disabled || (this.setChecked(!this.getChecked()), this.bubble("onchange")), !this.disabled; +}, +dragstart: function() {} +}); + +// Drawer.js + +enyo.kind({ +name: "onyx.Drawer", +published: { +open: !0, +orient: "v", +animated: !0 +}, +style: "overflow: hidden; position: relative;", +tools: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorEnd" +}, { +name: "client", +style: "position: relative;", +classes: "enyo-border-box" +} ], +create: function() { +this.inherited(arguments), this.animatedChanged(), this.openChanged(); +}, +initComponents: function() { +this.createChrome(this.tools), this.inherited(arguments); +}, +animatedChanged: function() { +!this.animated && this.hasNode() && this.$.animator.isAnimating() && (this.$.animator.stop(), this.animatorEnd()); +}, +openChanged: function() { +this.$.client.show(); +if (this.hasNode()) if (this.$.animator.isAnimating()) this.$.animator.reverse(); else { +var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left"; +this.applyStyle(t, null); +var r = this.hasNode()[e ? "scrollHeight" : "scrollWidth"]; +this.animated ? this.$.animator.play({ +startValue: this.open ? 0 : r, +endValue: this.open ? r : 0, +dimension: t, +position: n +}) : this.animatorEnd(); +} else this.$.client.setShowing(this.open); +}, +animatorStep: function(e) { +if (this.hasNode()) { +var t = e.dimension; +this.node.style[t] = this.domStyles[t] = e.value + "px"; +} +var n = this.$.client.hasNode(); +if (n) { +var r = e.position, i = this.open ? e.endValue : e.startValue; +n.style[r] = this.$.client.domStyles[r] = e.value - i + "px"; +} +this.container && this.container.resized(); +}, +animatorEnd: function() { +if (!this.open) this.$.client.hide(); else { +this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); +var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left", r = this.$.client.hasNode(); +r && (r.style[n] = this.$.client.domStyles[n] = null), this.node && (this.node.style[t] = this.domStyles[t] = null); +} +this.container && this.container.resized(); +} +}); + +// Grabber.js + +enyo.kind({ +name: "onyx.Grabber", +classes: "onyx-grabber" +}); + +// Groupbox.js + +enyo.kind({ +name: "onyx.Groupbox", +classes: "onyx-groupbox" +}), enyo.kind({ +name: "onyx.GroupboxHeader", +classes: "onyx-groupbox-header" +}); + +// Input.js + +enyo.kind({ +name: "onyx.Input", +kind: "enyo.Input", +classes: "onyx-input" +}); + +// Popup.js + +enyo.kind({ +name: "onyx.Popup", +kind: "Popup", +classes: "onyx-popup", +published: { +scrimWhenModal: !0, +scrim: !1, +scrimClassName: "" +}, +statics: { +count: 0 +}, +defaultZ: 120, +showingChanged: function() { +this.showing ? (onyx.Popup.count++, this.applyZIndex()) : onyx.Popup.count > 0 && onyx.Popup.count--, this.showHideScrim(this.showing), this.inherited(arguments); +}, +showHideScrim: function(e) { +if (this.floating && (this.scrim || this.modal && this.scrimWhenModal)) { +var t = this.getScrim(); +if (e) { +var n = this.getScrimZIndex(); +this._scrimZ = n, t.showAtZIndex(n); +} else t.hideAtZIndex(this._scrimZ); +enyo.call(t, "addRemoveClass", [ this.scrimClassName, t.showing ]); +} +}, +getScrimZIndex: function() { +return this.findZIndex() - 1; +}, +getScrim: function() { +return this.modal && this.scrimWhenModal && !this.scrim ? onyx.scrimTransparent.make() : onyx.scrim.make(); +}, +applyZIndex: function() { +this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1, this.applyStyle("z-index", this._zIndex); +}, +findZIndex: function() { +var e = this.defaultZ; +return this._zIndex ? e = this._zIndex : this.hasNode() && (e = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || e), this._zIndex = e; +} +}); + +// TextArea.js + +enyo.kind({ +name: "onyx.TextArea", +kind: "enyo.TextArea", +classes: "onyx-textarea" +}); + +// RichText.js + +enyo.kind({ +name: "onyx.RichText", +kind: "enyo.RichText", +classes: "onyx-richtext" +}); + +// InputDecorator.js + +enyo.kind({ +name: "onyx.InputDecorator", +kind: "enyo.ToolDecorator", +tag: "label", +classes: "onyx-input-decorator", +published: { +alwaysLooksFocused: !1 +}, +handlers: { +onDisabledChange: "disabledChange", +onfocus: "receiveFocus", +onblur: "receiveBlur" +}, +create: function() { +this.inherited(arguments), this.updateFocus(!1); +}, +alwaysLooksFocusedChanged: function(e) { +this.updateFocus(this.focus); +}, +updateFocus: function(e) { +this.focused = e, this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); +}, +receiveFocus: function() { +this.updateFocus(!0); +}, +receiveBlur: function() { +this.updateFocus(!1); +}, +disabledChange: function(e, t) { +this.addRemoveClass("onyx-disabled", t.originator.disabled); +} +}); + +// Tooltip.js + +enyo.kind({ +name: "onyx.Tooltip", +kind: "onyx.Popup", +classes: "onyx-tooltip below left-arrow", +autoDismiss: !1, +showDelay: 500, +defaultLeft: -6, +handlers: { +onRequestShowTooltip: "requestShow", +onRequestHideTooltip: "requestHide" +}, +requestShow: function() { +return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; +}, +cancelShow: function() { +clearTimeout(this.showJob); +}, +requestHide: function() { +return this.cancelShow(), this.inherited(arguments); +}, +showingChanged: function() { +this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +adjustPosition: function(e) { +if (this.showing && this.hasNode()) { +var t = this.node.getBoundingClientRect(); +t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ +"margin-left": -t.width, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); +} +}, +resizeHandler: function() { +this.applyPosition({ +"margin-left": this.defaultLeft, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); +} +}); + +// TooltipDecorator.js + +enyo.kind({ +name: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator", +handlers: { +onenter: "enter", +onleave: "leave" +}, +enter: function() { +this.requestShowTooltip(); +}, +leave: function() { +this.requestHideTooltip(); +}, +tap: function() { +this.requestHideTooltip(); +}, +requestShowTooltip: function() { +this.waterfallDown("onRequestShowTooltip"); +}, +requestHideTooltip: function() { +this.waterfallDown("onRequestHideTooltip"); +} +}); + +// MenuDecorator.js + +enyo.kind({ +name: "onyx.MenuDecorator", +kind: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator enyo-unselectable", +handlers: { +onActivate: "activated", +onHide: "menuHidden" +}, +activated: function(e, t) { +this.requestHideTooltip(), t.originator.active && (this.menuActive = !0, this.activator = t.originator, this.activator.addClass("active"), this.requestShowMenu()); +}, +requestShowMenu: function() { +this.waterfallDown("onRequestShowMenu", { +activator: this.activator +}); +}, +requestHideMenu: function() { +this.waterfallDown("onRequestHideMenu"); +}, +menuHidden: function() { +this.menuActive = !1, this.activator && (this.activator.setActive(!1), this.activator.removeClass("active")); +}, +enter: function(e) { +this.menuActive || this.inherited(arguments); +}, +leave: function(e, t) { +this.menuActive || this.inherited(arguments); +} +}); + +// Menu.js + +enyo.kind({ +name: "onyx.Menu", +kind: "onyx.Popup", +modal: !0, +defaultKind: "onyx.MenuItem", +classes: "onyx-menu", +published: { +maxHeight: 200, +scrolling: !0 +}, +handlers: { +onActivate: "itemActivated", +onRequestShowMenu: "requestMenuShow", +onRequestHideMenu: "requestHide" +}, +childComponents: [ { +name: "client", +kind: "enyo.Scroller", +strategyKind: "TouchScrollStrategy" +} ], +showOnTop: !1, +scrollerName: "client", +create: function() { +this.inherited(arguments), this.maxHeightChanged(); +}, +initComponents: function() { +this.scrolling && this.createComponents(this.childComponents, { +isChrome: !0 +}), this.inherited(arguments); +}, +getScroller: function() { +return this.$[this.scrollerName]; +}, +maxHeightChanged: function() { +this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); +}, +itemActivated: function(e, t) { +return t.originator.setActive(!1), !0; +}, +showingChanged: function() { +this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(!0); +}, +requestMenuShow: function(e, t) { +if (this.floating) { +var n = t.activator.hasNode(); +if (n) { +var r = this.activatorOffset = this.getPageOffset(n); +this.applyPosition({ +top: r.top + (this.showOnTop ? 0 : r.height), +left: r.left, +width: r.width +}); +} +} +return this.show(), !0; +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +getPageOffset: function(e) { +var t = e.getBoundingClientRect(), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; +return { +top: t.top + n, +left: t.left + r, +height: i, +width: s +}; +}, +adjustPosition: function() { +if (this.showing && this.hasNode()) { +this.scrolling && !this.showOnTop && this.getScroller().setMaxHeight(this.maxHeight + "px"), this.removeClass("onyx-menu-up"), this.floating || this.applyPosition({ +left: "auto" +}); +var e = this.node.getBoundingClientRect(), t = e.height === undefined ? e.bottom - e.top : e.height, n = window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight, r = window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; +this.menuUp = e.top + t > n && n - e.bottom < e.top - t, this.addRemoveClass("onyx-menu-up", this.menuUp); +if (this.floating) { +var i = this.activatorOffset; +this.menuUp ? this.applyPosition({ +top: i.top - t + (this.showOnTop ? i.height : 0), +bottom: "auto" +}) : e.top < i.top && i.top + (this.showOnTop ? 0 : i.height) + t < n && this.applyPosition({ +top: i.top + (this.showOnTop ? 0 : i.height), +bottom: "auto" +}); +} +e.right > r && (this.floating ? this.applyPosition({ +left: r - e.width +}) : this.applyPosition({ +left: -(e.right - r) +})), e.left < 0 && (this.floating ? this.applyPosition({ +left: 0, +right: "auto" +}) : this.getComputedStyleValue("right") == "auto" ? this.applyPosition({ +left: -e.left +}) : this.applyPosition({ +right: e.left +})); +if (this.scrolling && !this.showOnTop) { +e = this.node.getBoundingClientRect(); +var s; +this.menuUp ? s = this.maxHeight < e.bottom ? this.maxHeight : e.bottom : s = e.top + this.maxHeight < n ? this.maxHeight : n - e.top, this.getScroller().setMaxHeight(s + "px"); +} +} +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +}, +requestHide: function() { +this.setShowing(!1); +} +}); + +// MenuItem.js + +enyo.kind({ +name: "onyx.MenuItem", +kind: "enyo.Button", +events: { +onSelect: "", +onItemContentChange: "" +}, +classes: "onyx-menu-item", +tag: "div", +create: function() { +this.inherited(arguments), this.active && this.bubble("onActivate"); +}, +tap: function(e) { +this.inherited(arguments), this.bubble("onRequestHideMenu"), this.doSelect({ +selected: this, +content: this.content +}); +}, +contentChanged: function(e) { +this.inherited(arguments), this.doItemContentChange({ +content: this.content +}); +} +}); + +// PickerDecorator.js + +enyo.kind({ +name: "onyx.PickerDecorator", +kind: "onyx.MenuDecorator", +classes: "onyx-picker-decorator", +defaultKind: "onyx.PickerButton", +handlers: { +onChange: "change" +}, +change: function(e, t) { +this.waterfallDown("onChange", t); +} +}); + +// PickerButton.js + +enyo.kind({ +name: "onyx.PickerButton", +kind: "onyx.Button", +handlers: { +onChange: "change" +}, +change: function(e, t) { +t.content !== undefined && this.setContent(t.content); +} +}); + +// Picker.js + +enyo.kind({ +name: "onyx.Picker", +kind: "onyx.Menu", +classes: "onyx-picker enyo-unselectable", +published: { +selected: null +}, +events: { +onChange: "" +}, +handlers: { +onItemContentChange: "itemContentChange" +}, +floating: !0, +showOnTop: !0, +initComponents: function() { +this.setScrolling(!0), this.inherited(arguments); +}, +showingChanged: function() { +this.getScroller().setShowing(this.showing), this.inherited(arguments), this.showing && this.selected && this.scrollToSelected(); +}, +scrollToSelected: function() { +this.getScroller().scrollToControl(this.selected, !this.menuUp); +}, +itemActivated: function(e, t) { +return this.processActivatedItem(t.originator), this.inherited(arguments); +}, +processActivatedItem: function(e) { +e.active && this.setSelected(e); +}, +selectedChanged: function(e) { +e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ +selected: this.selected, +content: this.selected.content +})); +}, +itemContentChange: function(e, t) { +t.originator == this.selected && this.doChange({ +selected: this.selected, +content: this.selected.content +}); +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +} +}); + +// FlyweightPicker.js + +enyo.kind({ +name: "onyx.FlyweightPicker", +kind: "onyx.Picker", +classes: "onyx-flyweight-picker", +published: { +count: 0 +}, +events: { +onSetupItem: "", +onSelect: "" +}, +handlers: { +onSelect: "itemSelect" +}, +components: [ { +name: "scroller", +kind: "enyo.Scroller", +strategyKind: "TouchScrollStrategy", +components: [ { +name: "flyweight", +kind: "FlyweightRepeater", +noSelect: !0, +ontap: "itemTap" +} ] +} ], +scrollerName: "scroller", +initComponents: function() { +this.controlParentName = "flyweight", this.inherited(arguments), this.$.flyweight.$.client.children[0].setActive(!0); +}, +create: function() { +this.inherited(arguments), this.countChanged(); +}, +rendered: function() { +this.inherited(arguments), this.selectedChanged(); +}, +scrollToSelected: function() { +var e = this.$.flyweight.fetchRowNode(this.selected); +this.getScroller().scrollToNode(e, !this.menuUp); +}, +countChanged: function() { +this.$.flyweight.count = this.count; +}, +processActivatedItem: function(e) { +this.item = e; +}, +selectedChanged: function(e) { +if (!this.item) return; +e != null && (this.item.removeClass("selected"), this.$.flyweight.renderRow(e)); +var t; +this.selected != null && (this.item.addClass("selected"), this.$.flyweight.renderRow(this.selected), this.item.removeClass("selected"), t = this.$.flyweight.fetchRowNode(this.selected)), this.doChange({ +selected: this.selected, +content: t && t.textContent || this.item.content +}); +}, +itemTap: function(e, t) { +this.setSelected(t.rowIndex), this.doSelect({ +selected: this.item, +content: this.item.content +}); +}, +itemSelect: function(e, t) { +if (t.originator != this) return !0; +} +}); + +// DatePicker.js + +enyo.kind({ +name: "onyx.DatePicker", +classes: "onyx-toolbar-inline", +published: { +disabled: !1, +locale: "en_us", +dayHidden: !1, +monthHidden: !1, +yearHidden: !1, +minYear: 1900, +maxYear: 2099, +value: null +}, +events: { +onSelect: "" +}, +create: function() { +this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); +}, +initDefaults: function() { +var e = [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; +enyo.g11n && (this._tf = new enyo.g11n.Fmts({ +locale: this.locale +}), e = this._tf.getMonthFields()), this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : "mdy"), this.dayHiddenChanged(), this.monthHiddenChanged(), this.yearHiddenChanged(); +var t = this.value = this.value || new Date; +for (var n = 0, r; r = e[n]; n++) this.$.monthPicker.createComponent({ +content: r, +value: n, +active: n == t.getMonth() +}); +var i = t.getFullYear(); +this.$.yearPicker.setSelected(i - this.minYear); +for (n = 1; n <= this.monthLength(t.getYear(), t.getMonth()); n++) this.$.dayPicker.createComponent({ +content: n, +value: n, +active: n == t.getDate() +}); +}, +monthLength: function(e, t) { +return 32 - (new Date(e, t, 32)).getDate(); +}, +setupYear: function(e, t) { +this.$.year.setContent(this.minYear + t.index); +}, +setupPickers: function(e) { +var t = e.split(""), n, r, i; +for (r = 0, i = t.length; r < i; r++) { +n = t[r]; +switch (n) { +case "d": +this.createDay(); +break; +case "m": +this.createMonth(); +break; +case "y": +this.createYear(); +break; +default: +} +} +}, +createYear: function() { +var e = this.maxYear - this.minYear; +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateYear", +components: [ { +classes: "onyx-datepicker-year", +name: "yearPickerButton", +disabled: this.disabled +}, { +name: "yearPicker", +kind: "onyx.FlyweightPicker", +count: ++e, +onSetupItem: "setupYear", +components: [ { +name: "year" +} ] +} ] +}); +}, +createMonth: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateMonth", +components: [ { +classes: "onyx-datepicker-month", +name: "monthPickerButton", +disabled: this.disabled +}, { +name: "monthPicker", +kind: "onyx.Picker" +} ] +}); +}, +createDay: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateDay", +components: [ { +classes: "onyx-datepicker-day", +name: "dayPickerButton", +disabled: this.disabled +}, { +name: "dayPicker", +kind: "onyx.Picker" +} ] +}); +}, +localeChanged: function() { +this.refresh(); +}, +dayHiddenChanged: function() { +this.$.dayPicker.getParent().setShowing(this.dayHidden ? !1 : !0); +}, +monthHiddenChanged: function() { +this.$.monthPicker.getParent().setShowing(this.monthHidden ? !1 : !0); +}, +yearHiddenChanged: function() { +this.$.yearPicker.getParent().setShowing(this.yearHidden ? !1 : !0); +}, +minYearChanged: function() { +this.refresh(); +}, +maxYearChanged: function() { +this.refresh(); +}, +valueChanged: function() { +this.refresh(); +}, +disabledChanged: function() { +this.$.yearPickerButton.setDisabled(this.disabled), this.$.monthPickerButton.setDisabled(this.disabled), this.$.dayPickerButton.setDisabled(this.disabled); +}, +updateDay: function(e, t) { +var n = this.calcDate(this.value.getFullYear(), this.value.getMonth(), t.selected.value); +return this.doSelect({ +name: this.name, +value: n +}), this.setValue(n), !0; +}, +updateMonth: function(e, t) { +var n = this.calcDate(this.value.getFullYear(), t.selected.value, this.value.getDate()); +return this.doSelect({ +name: this.name, +value: n +}), this.setValue(n), !0; +}, +updateYear: function(e, t) { +if (t.originator.selected != -1) { +var n = this.calcDate(this.minYear + t.originator.selected, this.value.getMonth(), this.value.getDate()); +this.doSelect({ +name: this.name, +value: n +}), this.setValue(n); +} +return !0; +}, +calcDate: function(e, t, n) { +return new Date(e, t, n, this.value.getHours(), this.value.getMinutes(), this.value.getSeconds(), this.value.getMilliseconds()); +}, +refresh: function() { +this.destroyClientControls(), this.initDefaults(), this.render(); +} +}); + +// TimePicker.js + +enyo.kind({ +name: "onyx.TimePicker", +classes: "onyx-toolbar-inline", +published: { +disabled: !1, +locale: "en_us", +is24HrMode: null, +value: null +}, +events: { +onSelect: "" +}, +create: function() { +this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); +}, +initDefaults: function() { +var e = "AM", t = "PM"; +this.is24HrMode == null && (this.is24HrMode = !1), enyo.g11n && (this._tf = new enyo.g11n.Fmts({ +locale: this.locale +}), e = this._tf.getAmCaption(), t = this._tf.getPmCaption(), this.is24HrMode == null && (this.is24HrMode = !this._tf.isAmPm())), this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : "hma"); +var n = this.value = this.value || new Date, r; +if (!this.is24HrMode) { +var i = n.getHours(); +i = i === 0 ? 12 : i; +for (r = 1; r <= 12; r++) this.$.hourPicker.createComponent({ +content: r, +value: r, +active: r == (i > 12 ? i % 12 : i) +}); +} else for (r = 0; r < 24; r++) this.$.hourPicker.createComponent({ +content: r, +value: r, +active: r == n.getHours() +}); +for (r = 0; r <= 59; r++) this.$.minutePicker.createComponent({ +content: r < 10 ? "0" + r : r, +value: r, +active: r == n.getMinutes() +}); +n.getHours() >= 12 ? this.$.ampmPicker.createComponents([ { +content: e +}, { +content: t, +active: !0 +} ]) : this.$.ampmPicker.createComponents([ { +content: e, +active: !0 +}, { +content: t +} ]), this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); +}, +setupPickers: function(e) { +var t = e.split(""), n, r, i; +for (r = 0, i = t.length; r < i; r++) { +n = t[r]; +switch (n) { +case "h": +this.createHour(); +break; +case "m": +this.createMinute(); +break; +case "a": +this.createAmPm(); +break; +default: +} +} +}, +createHour: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateHour", +components: [ { +classes: "onyx-timepicker-hour", +name: "hourPickerButton", +disabled: this.disabled +}, { +name: "hourPicker", +kind: "onyx.Picker" +} ] +}); +}, +createMinute: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateMinute", +components: [ { +classes: "onyx-timepicker-minute", +name: "minutePickerButton", +disabled: this.disabled +}, { +name: "minutePicker", +kind: "onyx.Picker" +} ] +}); +}, +createAmPm: function() { +this.createComponent({ +kind: "onyx.PickerDecorator", +onSelect: "updateAmPm", +components: [ { +classes: "onyx-timepicker-ampm", +name: "ampmPickerButton", +disabled: this.disabled +}, { +name: "ampmPicker", +kind: "onyx.Picker" +} ] +}); +}, +disabledChanged: function() { +this.$.hourPickerButton.setDisabled(this.disabled), this.$.minutePickerButton.setDisabled(this.disabled), this.$.ampmPickerButton.setDisabled(this.disabled); +}, +localeChanged: function() { +this.is24HrMode = null, this.refresh(); +}, +is24HrModeChanged: function() { +this.refresh(); +}, +valueChanged: function() { +this.refresh(); +}, +updateHour: function(e, t) { +var n = t.selected.value; +if (!this.is24HrMode) { +var r = this.$.ampmPicker.getParent().controlAtIndex(0).content; +n = n + (n == 12 ? -12 : 0) + (this.isAm(r) ? 0 : 12); +} +return this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +updateMinute: function(e, t) { +return this.value = this.calcTime(this.value.getHours(), t.selected.value), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +updateAmPm: function(e, t) { +var n = this.value.getHours(); +return this.is24HrMode || (n += n > 11 ? this.isAm(t.content) ? -12 : 0 : this.isAm(t.content) ? 0 : 12), this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ +name: this.name, +value: this.value +}), !0; +}, +calcTime: function(e, t) { +return new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), e, t, this.value.getSeconds(), this.value.getMilliseconds()); +}, +isAm: function(e) { +var t, n, r; +try { +t = this._tf.getAmCaption(), n = this._tf.getPmCaption(); +} catch (i) { +t = "AM", n = "PM"; +} +return e == t ? !0 : !1; +}, +refresh: function() { +this.destroyClientControls(), this.initDefaults(), this.render(); +} +}); + +// RadioButton.js + +enyo.kind({ +name: "onyx.RadioButton", +kind: "Button", +classes: "onyx-radiobutton" +}); + +// RadioGroup.js + +enyo.kind({ +name: "onyx.RadioGroup", +kind: "Group", +defaultKind: "onyx.RadioButton", +highlander: !0 +}); + +// ToggleButton.js + +enyo.kind({ +name: "onyx.ToggleButton", +classes: "onyx-toggle-button", +published: { +active: !1, +value: !1, +onContent: "On", +offContent: "Off", +disabled: !1 +}, +events: { +onChange: "" +}, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +components: [ { +name: "contentOn", +classes: "onyx-toggle-content on" +}, { +name: "contentOff", +classes: "onyx-toggle-content off" +}, { +classes: "onyx-toggle-button-knob" +} ], +create: function() { +this.inherited(arguments), this.value = Boolean(this.value || this.active), this.onContentChanged(), this.offContentChanged(), this.disabledChanged(); +}, +rendered: function() { +this.inherited(arguments), this.updateVisualState(); +}, +updateVisualState: function() { +this.addRemoveClass("off", !this.value), this.$.contentOn.setShowing(this.value), this.$.contentOff.setShowing(!this.value), this.setActive(this.value); +}, +valueChanged: function() { +this.updateVisualState(), this.doChange({ +value: this.value +}); +}, +activeChanged: function() { +this.setValue(this.active), this.bubble("onActivate"); +}, +onContentChanged: function() { +this.$.contentOn.setContent(this.onContent || ""), this.$.contentOn.addRemoveClass("empty", !this.onContent); +}, +offContentChanged: function() { +this.$.contentOff.setContent(this.offContent || ""), this.$.contentOff.addRemoveClass("empty", !this.onContent); +}, +disabledChanged: function() { +this.addRemoveClass("disabled", this.disabled); +}, +updateValue: function(e) { +this.disabled || this.setValue(e); +}, +tap: function() { +this.updateValue(!this.value); +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, this.dragged = !1, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = t.dx; +return Math.abs(n) > 10 && (this.updateValue(n > 0), this.dragged = !0), !0; +} +}, +dragfinish: function(e, t) { +this.dragging = !1, this.dragged && t.preventTap(); +} +}); + +// ToggleIconButton.js + +enyo.kind({ +name: "onyx.ToggleIconButton", +kind: "onyx.Icon", +published: { +active: !1, +value: !1 +}, +events: { +onChange: "" +}, +classes: "onyx-icon-button onyx-icon-toggle", +activeChanged: function() { +this.addRemoveClass("active", this.value), this.bubble("onActivate"); +}, +updateValue: function(e) { +this.disabled || (this.setValue(e), this.doChange({ +value: this.value +})); +}, +tap: function() { +this.updateValue(!this.value); +}, +valueChanged: function() { +this.setActive(this.value); +}, +create: function() { +this.inherited(arguments), this.value = Boolean(this.value || this.active); +}, +rendered: function() { +this.inherited(arguments), this.valueChanged(), this.removeClass("onyx-icon"); +} +}); + +// Toolbar.js + +enyo.kind({ +name: "onyx.Toolbar", +classes: "onyx onyx-toolbar onyx-toolbar-inline", +create: function() { +this.inherited(arguments), this.hasClass("onyx-menu-toolbar") && enyo.platform.android >= 4 && this.applyStyle("position", "static"); +} +}); + +// Tooltip.js + +enyo.kind({ +name: "onyx.Tooltip", +kind: "onyx.Popup", +classes: "onyx-tooltip below left-arrow", +autoDismiss: !1, +showDelay: 500, +defaultLeft: -6, +handlers: { +onRequestShowTooltip: "requestShow", +onRequestHideTooltip: "requestHide" +}, +requestShow: function() { +return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; +}, +cancelShow: function() { +clearTimeout(this.showJob); +}, +requestHide: function() { +return this.cancelShow(), this.inherited(arguments); +}, +showingChanged: function() { +this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +adjustPosition: function(e) { +if (this.showing && this.hasNode()) { +var t = this.node.getBoundingClientRect(); +t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ +"margin-left": -t.width, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); +} +}, +resizeHandler: function() { +this.applyPosition({ +"margin-left": this.defaultLeft, +bottom: "auto" +}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); +} +}); + +// TooltipDecorator.js + +enyo.kind({ +name: "onyx.TooltipDecorator", +defaultKind: "onyx.Button", +classes: "onyx-popup-decorator", +handlers: { +onenter: "enter", +onleave: "leave" +}, +enter: function() { +this.requestShowTooltip(); +}, +leave: function() { +this.requestHideTooltip(); +}, +tap: function() { +this.requestHideTooltip(); +}, +requestShowTooltip: function() { +this.waterfallDown("onRequestShowTooltip"); +}, +requestHideTooltip: function() { +this.waterfallDown("onRequestHideTooltip"); +} +}); + +// ProgressBar.js + +enyo.kind({ +name: "onyx.ProgressBar", +classes: "onyx-progress-bar", +published: { +progress: 0, +min: 0, +max: 100, +barClasses: "", +showStripes: !0, +animateStripes: !0, +increment: 0 +}, +events: { +onAnimateProgressFinish: "" +}, +components: [ { +name: "progressAnimator", +kind: "Animator", +onStep: "progressAnimatorStep", +onEnd: "progressAnimatorComplete" +}, { +name: "bar", +classes: "onyx-progress-bar-bar" +} ], +create: function() { +this.inherited(arguments), this.progressChanged(), this.barClassesChanged(), this.showStripesChanged(), this.animateStripesChanged(); +}, +barClassesChanged: function(e) { +this.$.bar.removeClass(e), this.$.bar.addClass(this.barClasses); +}, +showStripesChanged: function() { +this.$.bar.addRemoveClass("striped", this.showStripes); +}, +animateStripesChanged: function() { +this.$.bar.addRemoveClass("animated", this.animateStripes); +}, +progressChanged: function() { +this.progress = this.clampValue(this.min, this.max, this.progress); +var e = this.calcPercent(this.progress); +this.updateBarPosition(e); +}, +calcIncrement: function(e) { +return Math.round(e / this.increment) * this.increment; +}, +clampValue: function(e, t, n) { +return Math.max(e, Math.min(n, t)); +}, +calcRatio: function(e) { +return (e - this.min) / (this.max - this.min); +}, +calcPercent: function(e) { +return this.calcRatio(e) * 100; +}, +updateBarPosition: function(e) { +this.$.bar.applyStyle("width", e + "%"); +}, +animateProgressTo: function(e) { +this.$.progressAnimator.play({ +startValue: this.progress, +endValue: e, +node: this.hasNode() +}); +}, +progressAnimatorStep: function(e) { +return this.setProgress(e.value), !0; +}, +progressAnimatorComplete: function(e) { +return this.doAnimateProgressFinish(e), !0; +} +}); + +// ProgressButton.js + +enyo.kind({ +name: "onyx.ProgressButton", +kind: "onyx.ProgressBar", +classes: "onyx-progress-button", +events: { +onCancel: "" +}, +components: [ { +name: "progressAnimator", +kind: "Animator", +onStep: "progressAnimatorStep", +onEnd: "progressAnimatorComplete" +}, { +name: "bar", +classes: "onyx-progress-bar-bar onyx-progress-button-bar" +}, { +name: "client", +classes: "onyx-progress-button-client" +}, { +kind: "onyx.Icon", +src: "$lib/onyx/images/progress-button-cancel.png", +classes: "onyx-progress-button-icon", +ontap: "cancelTap" +} ], +cancelTap: function() { +this.doCancel(); +} +}); + +// Scrim.js + +enyo.kind({ +name: "onyx.Scrim", +showing: !1, +classes: "onyx-scrim enyo-fit", +floating: !1, +create: function() { +this.inherited(arguments), this.zStack = [], this.floating && this.setParent(enyo.floatingLayer); +}, +showingChanged: function() { +this.floating && this.showing && !this.hasNode() && this.render(), this.inherited(arguments); +}, +addZIndex: function(e) { +enyo.indexOf(e, this.zStack) < 0 && this.zStack.push(e); +}, +removeZIndex: function(e) { +enyo.remove(e, this.zStack); +}, +showAtZIndex: function(e) { +this.addZIndex(e), e !== undefined && this.setZIndex(e), this.show(); +}, +hideAtZIndex: function(e) { +this.removeZIndex(e); +if (!this.zStack.length) this.hide(); else { +var t = this.zStack[this.zStack.length - 1]; +this.setZIndex(t); +} +}, +setZIndex: function(e) { +this.zIndex = e, this.applyStyle("z-index", e); +}, +make: function() { +return this; +} +}), enyo.kind({ +name: "onyx.scrimSingleton", +kind: null, +constructor: function(e, t) { +this.instanceName = e, enyo.setObject(this.instanceName, this), this.props = t || {}; +}, +make: function() { +var e = new onyx.Scrim(this.props); +return enyo.setObject(this.instanceName, e), e; +}, +showAtZIndex: function(e) { +var t = this.make(); +t.showAtZIndex(e); +}, +hideAtZIndex: enyo.nop, +show: function() { +var e = this.make(); +e.show(); +} +}), new onyx.scrimSingleton("onyx.scrim", { +floating: !0, +classes: "onyx-scrim-translucent" +}), new onyx.scrimSingleton("onyx.scrimTransparent", { +floating: !0, +classes: "onyx-scrim-transparent" +}); + +// Slider.js + +enyo.kind({ +name: "onyx.Slider", +kind: "onyx.ProgressBar", +classes: "onyx-slider", +published: { +value: 0, +lockBar: !0, +tappable: !0 +}, +events: { +onChange: "", +onChanging: "", +onAnimateFinish: "" +}, +showStripes: !1, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish" +}, +moreComponents: [ { +kind: "Animator", +onStep: "animatorStep", +onEnd: "animatorComplete" +}, { +classes: "onyx-slider-taparea" +}, { +name: "knob", +classes: "onyx-slider-knob" +} ], +create: function() { +this.inherited(arguments), enyo.platform.firefoxOS && (this.moreComponents[2].ondown = "down", this.moreComponents[2].onleave = "leave"), this.createComponents(this.moreComponents), this.valueChanged(); +}, +valueChanged: function() { +this.value = this.clampValue(this.min, this.max, this.value); +var e = this.calcPercent(this.value); +this.updateKnobPosition(e), this.lockBar && this.setProgress(this.value); +}, +updateKnobPosition: function(e) { +this.$.knob.applyStyle("left", e + "%"); +}, +calcKnobPosition: function(e) { +var t = e.clientX - this.hasNode().getBoundingClientRect().left; +return t / this.getBounds().width * (this.max - this.min) + this.min; +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = this.calcKnobPosition(t); +return n = this.increment ? this.calcIncrement(n) : n, this.setValue(n), this.doChanging({ +value: this.value +}), !0; +} +}, +dragfinish: function(e, t) { +return this.dragging = !1, t.preventTap(), this.doChange({ +value: this.value +}), !0; +}, +tap: function(e, t) { +if (this.tappable) { +var n = this.calcKnobPosition(t); +return n = this.increment ? this.calcIncrement(n) : n, this.tapped = !0, this.animateTo(n), !0; +} +}, +down: function(e, t) { +this.addClass("pressed"); +}, +leave: function(e, t) { +this.removeClass("pressed"); +}, +animateTo: function(e) { +this.$.animator.play({ +startValue: this.value, +endValue: e, +node: this.hasNode() +}); +}, +animatorStep: function(e) { +return this.setValue(e.value), !0; +}, +animatorComplete: function(e) { +return this.tapped && (this.tapped = !1, this.doChange({ +value: this.value +})), this.doAnimateFinish(e), !0; +} +}); + +// RangeSlider.js + +enyo.kind({ +name: "onyx.RangeSlider", +kind: "onyx.ProgressBar", +classes: "onyx-slider", +published: { +rangeMin: 0, +rangeMax: 100, +rangeStart: 0, +rangeEnd: 100, +beginValue: 0, +endValue: 0 +}, +events: { +onChange: "", +onChanging: "" +}, +showStripes: !1, +showLabels: !1, +handlers: { +ondragstart: "dragstart", +ondrag: "drag", +ondragfinish: "dragfinish", +ondown: "down" +}, +moreComponents: [ { +name: "startKnob", +classes: "onyx-slider-knob" +}, { +name: "endKnob", +classes: "onyx-slider-knob onyx-range-slider-knob" +} ], +create: function() { +this.inherited(arguments), this.createComponents(this.moreComponents), this.initControls(); +}, +rendered: function() { +this.inherited(arguments); +var e = this.calcPercent(this.beginValue); +this.updateBarPosition(e); +}, +initControls: function() { +this.$.bar.applyStyle("position", "relative"), this.refreshRangeSlider(), this.showLabels && (this.$.startKnob.createComponent({ +name: "startLabel", +kind: "onyx.RangeSliderKnobLabel" +}), this.$.endKnob.createComponent({ +name: "endLabel", +kind: "onyx.RangeSliderKnobLabel" +})); +}, +refreshRangeSlider: function() { +this.beginValue = this.calcKnobPercent(this.rangeStart), this.endValue = this.calcKnobPercent(this.rangeEnd), this.beginValueChanged(), this.endValueChanged(); +}, +calcKnobRatio: function(e) { +return (e - this.rangeMin) / (this.rangeMax - this.rangeMin); +}, +calcKnobPercent: function(e) { +return this.calcKnobRatio(e) * 100; +}, +beginValueChanged: function(e) { +if (e === undefined) { +var t = this.calcPercent(this.beginValue); +this.updateKnobPosition(t, this.$.startKnob); +} +}, +endValueChanged: function(e) { +if (e === undefined) { +var t = this.calcPercent(this.endValue); +this.updateKnobPosition(t, this.$.endKnob); +} +}, +calcKnobPosition: function(e) { +var t = e.clientX - this.hasNode().getBoundingClientRect().left; +return t / this.getBounds().width * (this.max - this.min) + this.min; +}, +updateKnobPosition: function(e, t) { +t.applyStyle("left", e + "%"), this.updateBarPosition(); +}, +updateBarPosition: function() { +if (this.$.startKnob !== undefined && this.$.endKnob !== undefined) { +var e = this.calcKnobPercent(this.rangeStart), t = this.calcKnobPercent(this.rangeEnd) - e; +this.$.bar.applyStyle("left", e + "%"), this.$.bar.applyStyle("width", t + "%"); +} +}, +calcRangeRatio: function(e) { +return e / 100 * (this.rangeMax - this.rangeMin) + this.rangeMin - this.increment / 2; +}, +swapZIndex: function(e) { +e === "startKnob" ? (this.$.startKnob.applyStyle("z-index", 1), this.$.endKnob.applyStyle("z-index", 0)) : e === "endKnob" && (this.$.startKnob.applyStyle("z-index", 0), this.$.endKnob.applyStyle("z-index", 1)); +}, +down: function(e, t) { +this.swapZIndex(e.name); +}, +dragstart: function(e, t) { +if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; +}, +drag: function(e, t) { +if (this.dragging) { +var n = this.calcKnobPosition(t), r, i, s; +if (e.name === "startKnob" && n >= 0) { +if (!(n <= this.endValue && t.xDirection === -1 || n <= this.endValue)) return this.drag(this.$.endKnob, t); +this.setBeginValue(n), r = this.calcRangeRatio(this.beginValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.startKnob), this.setRangeStart(i), this.doChanging({ +value: i +}); +} else if (e.name === "endKnob" && n <= 100) { +if (!(n >= this.beginValue && t.xDirection === 1 || n >= this.beginValue)) return this.drag(this.$.startKnob, t); +this.setEndValue(n), r = this.calcRangeRatio(this.endValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.endKnob), this.setRangeEnd(i), this.doChanging({ +value: i +}); +} +return !0; +} +}, +dragfinish: function(e, t) { +this.dragging = !1, t.preventTap(); +var n; +return e.name === "startKnob" ? (n = this.calcRangeRatio(this.beginValue), this.doChange({ +value: n, +startChanged: !0 +})) : e.name === "endKnob" && (n = this.calcRangeRatio(this.endValue), this.doChange({ +value: n, +startChanged: !1 +})), !0; +}, +rangeMinChanged: function() { +this.refreshRangeSlider(); +}, +rangeMaxChanged: function() { +this.refreshRangeSlider(); +}, +rangeStartChanged: function() { +this.refreshRangeSlider(); +}, +rangeEndChanged: function() { +this.refreshRangeSlider(); +}, +setStartLabel: function(e) { +this.$.startKnob.waterfallDown("onSetLabel", e); +}, +setEndLabel: function(e) { +this.$.endKnob.waterfallDown("onSetLabel", e); +} +}), enyo.kind({ +name: "onyx.RangeSliderKnobLabel", +classes: "onyx-range-slider-label", +handlers: { +onSetLabel: "setLabel" +}, +setLabel: function(e, t) { +this.setContent(t); +} +}); + +// Item.js + +enyo.kind({ +name: "onyx.Item", +classes: "onyx-item", +tapHighlight: !0, +handlers: { +onhold: "hold", +onrelease: "release" +}, +hold: function(e, t) { +this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !0, t); +}, +release: function(e, t) { +this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !1, t); +}, +statics: { +addRemoveFlyweightClass: function(e, t, n, r, i) { +var s = r.flyweight; +if (s) { +var o = i !== undefined ? i : r.index; +s.performOnRow(o, function() { +e.addRemoveClass(t, n); +}); +} +} +} +}); + +// Spinner.js + +enyo.kind({ +name: "onyx.Spinner", +classes: "onyx-spinner", +stop: function() { +this.setShowing(!1); +}, +start: function() { +this.setShowing(!0); +}, +toggle: function() { +this.setShowing(!this.getShowing()); +} +}); + +// MoreToolbar.js + +enyo.kind({ +name: "onyx.MoreToolbar", +classes: "onyx-toolbar onyx-more-toolbar", +menuClass: "", +movedClass: "", +layoutKind: "FittableColumnsLayout", +noStretch: !0, +handlers: { +onHide: "reflow" +}, +published: { +clientLayoutKind: "FittableColumnsLayout" +}, +tools: [ { +name: "client", +noStretch: !0, +fit: !0, +classes: "onyx-toolbar-inline" +}, { +name: "nard", +kind: "onyx.MenuDecorator", +showing: !1, +onActivate: "activated", +components: [ { +kind: "onyx.IconButton", +classes: "onyx-more-button" +}, { +name: "menu", +kind: "onyx.Menu", +scrolling: !1, +classes: "onyx-more-menu" +} ] +} ], +initComponents: function() { +this.menuClass && this.menuClass.length > 0 && !this.$.menu.hasClass(this.menuClass) && this.$.menu.addClass(this.menuClass), this.createChrome(this.tools), this.inherited(arguments), this.$.client.setLayoutKind(this.clientLayoutKind); +}, +clientLayoutKindChanged: function() { +this.$.client.setLayoutKind(this.clientLayoutKind); +}, +reflow: function() { +this.inherited(arguments), this.isContentOverflowing() ? (this.$.nard.show(), this.popItem() && this.reflow()) : this.tryPushItem() ? this.reflow() : this.$.menu.children.length || (this.$.nard.hide(), this.$.menu.hide()); +}, +activated: function(e, t) { +this.addRemoveClass("active", t.originator.active); +}, +popItem: function() { +var e = this.findCollapsibleItem(); +if (e) { +this.movedClass && this.movedClass.length > 0 && !e.hasClass(this.movedClass) && e.addClass(this.movedClass), this.$.menu.addChild(e, null); +var t = this.$.menu.hasNode(); +return t && e.hasNode() && e.insertNodeInParent(t), !0; +} +}, +pushItem: function() { +var e = this.$.menu.children, t = e[0]; +if (t) { +this.movedClass && this.movedClass.length > 0 && t.hasClass(this.movedClass) && t.removeClass(this.movedClass), this.$.client.addChild(t); +var n = this.$.client.hasNode(); +if (n && t.hasNode()) { +var r, i; +for (var s = 0; s < this.$.client.children.length; s++) { +var o = this.$.client.children[s]; +if (o.toolbarIndex !== undefined && o.toolbarIndex != s) { +r = o, i = s; +break; +} +} +if (r && r.hasNode()) { +t.insertNodeInParent(n, r.node); +var u = this.$.client.children.pop(); +this.$.client.children.splice(i, 0, u); +} else t.appendNodeToParent(n); +} +return !0; +} +}, +tryPushItem: function() { +if (this.pushItem()) { +if (!this.isContentOverflowing()) return !0; +this.popItem(); +} +}, +isContentOverflowing: function() { +if (this.$.client.hasNode()) { +var e = this.$.client.children, t = e[e.length - 1].hasNode(); +if (t) return this.$.client.reflow(), t.offsetLeft + t.offsetWidth > this.$.client.node.clientWidth; +} +}, +findCollapsibleItem: function() { +var e = this.$.client.children; +for (var t = e.length - 1; c = e[t]; t--) { +if (!c.unmoveable) return c; +c.toolbarIndex === undefined && (c.toolbarIndex = t); +} +} +}); + +// IntegerPicker.js + +enyo.kind({ +name: "onyx.IntegerPicker", +kind: "onyx.Picker", +published: { +value: 0, +min: 0, +max: 9 +}, +create: function() { +this.inherited(arguments), this.rangeChanged(); +}, +minChanged: function() { +this.destroyClientControls(), this.rangeChanged(), this.render(); +}, +maxChanged: function() { +this.destroyClientControls(), this.rangeChanged(), this.render(); +}, +rangeChanged: function() { +for (var e = this.min; e <= this.max; e++) this.createComponent({ +content: e, +active: e === this.value ? !0 : !1 +}); +}, +valueChanged: function(e) { +var t = this.getClientControls(), n = t.length; +this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; +for (var r = 0; r < n; r++) if (this.value === parseInt(t[r].content)) { +this.setSelected(t[r]); +break; +} +}, +selectedChanged: function(e) { +e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ +selected: this.selected, +content: this.selected.content +})), this.value = parseInt(this.selected.content); +} +}); + +// ContextualPopup.js + +enyo.kind({ +name: "onyx.ContextualPopup", +kind: "enyo.Popup", +modal: !0, +autoDismiss: !0, +floating: !1, +classes: "onyx-contextual-popup enyo-unselectable", +published: { +maxHeight: 100, +scrolling: !0, +title: undefined, +actionButtons: [] +}, +vertFlushMargin: 60, +horizFlushMargin: 50, +widePopup: 200, +longPopup: 200, +horizBuffer: 16, +events: { +onTap: "" +}, +handlers: { +onActivate: "itemActivated", +onRequestShowMenu: "requestShow", +onRequestHideMenu: "requestHide" +}, +components: [ { +name: "title", +classes: "onyx-contextual-popup-title" +}, { +classes: "onyx-contextual-popup-scroller", +components: [ { +name: "client", +kind: "enyo.Scroller", +vertical: "auto", +classes: "enyo-unselectable", +thumb: !1, +strategyKind: "TouchScrollStrategy" +} ] +}, { +name: "actionButtons", +classes: "onyx-contextual-popup-action-buttons" +} ], +scrollerName: "client", +create: function() { +this.inherited(arguments), this.maxHeightChanged(), this.titleChanged(), this.actionButtonsChanged(); +}, +getScroller: function() { +return this.$[this.scrollerName]; +}, +titleChanged: function() { +this.$.title.setContent(this.title); +}, +actionButtonsChanged: function() { +for (var e = 0; e < this.actionButtons.length; e++) this.$.actionButtons.createComponent({ +kind: "onyx.Button", +content: this.actionButtons[e].content, +classes: this.actionButtons[e].classes + " onyx-contextual-popup-action-button", +name: this.actionButtons[e].name ? this.actionButtons[e].name : "ActionButton" + e, +index: e, +tap: enyo.bind(this, this.tapHandler) +}); +}, +tapHandler: function(e, t) { +return t.actionButton = !0, t.popup = this, this.bubble("ontap", t), !0; +}, +maxHeightChanged: function() { +this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); +}, +itemActivated: function(e, t) { +return t.originator.setActive(!1), !0; +}, +showingChanged: function() { +this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(); +}, +requestShow: function(e, t) { +var n = t.activator.hasNode(); +return n && (this.activatorOffset = this.getPageOffset(n)), this.show(), !0; +}, +applyPosition: function(e) { +var t = ""; +for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); +this.addStyles(t); +}, +getPageOffset: function(e) { +var t = this.getBoundingRect(e), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; +return { +top: t.top + n, +left: t.left + r, +height: i, +width: s +}; +}, +adjustPosition: function() { +if (this.showing && this.hasNode()) { +this.resetPositioning(); +var e = this.getViewWidth(), t = this.getViewHeight(), n = this.vertFlushMargin, r = t - this.vertFlushMargin, i = this.horizFlushMargin, s = e - this.horizFlushMargin; +if (this.activatorOffset.top + this.activatorOffset.height < n || this.activatorOffset.top > r) { +if (this.applyVerticalFlushPositioning(i, s)) return; +if (this.applyHorizontalFlushPositioning(i, s)) return; +if (this.applyVerticalPositioning()) return; +} else if (this.activatorOffset.left + this.activatorOffset.width < i || this.activatorOffset.left > s) if (this.applyHorizontalPositioning()) return; +var o = this.getBoundingRect(this.node); +if (o.width > this.widePopup) { +if (this.applyVerticalPositioning()) return; +} else if (o.height > this.longPopup && this.applyHorizontalPositioning()) return; +if (this.applyVerticalPositioning()) return; +if (this.applyHorizontalPositioning()) return; +} +}, +initVerticalPositioning: function() { +this.resetPositioning(), this.addClass("vertical"); +var e = this.getBoundingRect(this.node), t = this.getViewHeight(); +return this.floating ? this.activatorOffset.top < t / 2 ? (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height, +bottom: "auto" +}), this.addClass("below")) : (this.applyPosition({ +top: this.activatorOffset.top - e.height, +bottom: "auto" +}), this.addClass("above")) : e.top + e.height > t && t - e.bottom < e.top - e.height ? this.addClass("above") : this.addClass("below"), e = this.getBoundingRect(this.node), e.top + e.height > t || e.top < 0 ? !1 : !0; +}, +applyVerticalPositioning: function() { +if (!this.initVerticalPositioning()) return !1; +var e = this.getBoundingRect(this.node), t = this.getViewWidth(); +if (this.floating) { +var n = this.activatorOffset.left + this.activatorOffset.width / 2 - e.width / 2; +n + e.width > t ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width - e.width +}), this.addClass("left")) : n < 0 ? (this.applyPosition({ +left: this.activatorOffset.left +}), this.addClass("right")) : this.applyPosition({ +left: n +}); +} else { +var r = this.activatorOffset.left + this.activatorOffset.width / 2 - e.left - e.width / 2; +e.right + r > t ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width - e.right +}), this.addRemoveClass("left", !0)) : e.left + r < 0 ? this.addRemoveClass("right", !0) : this.applyPosition({ +left: r +}); +} +return !0; +}, +applyVerticalFlushPositioning: function(e, t) { +if (!this.initVerticalPositioning()) return !1; +var n = this.getBoundingRect(this.node), r = this.getViewWidth(); +return this.activatorOffset.left + this.activatorOffset.width / 2 < e ? (this.activatorOffset.left + this.activatorOffset.width / 2 < this.horizBuffer ? this.applyPosition({ +left: this.horizBuffer + (this.floating ? 0 : -n.left) +}) : this.applyPosition({ +left: this.activatorOffset.width / 2 + (this.floating ? this.activatorOffset.left : 0) +}), this.addClass("right"), this.addClass("corner"), !0) : this.activatorOffset.left + this.activatorOffset.width / 2 > t ? (this.activatorOffset.left + this.activatorOffset.width / 2 > r - this.horizBuffer ? this.applyPosition({ +left: r - this.horizBuffer - n.right +}) : this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width / 2 - n.right +}), this.addClass("left"), this.addClass("corner"), !0) : !1; +}, +initHorizontalPositioning: function() { +this.resetPositioning(); +var e = this.getBoundingRect(this.node), t = this.getViewWidth(); +return this.floating ? this.activatorOffset.left + this.activatorOffset.width < t / 2 ? (this.applyPosition({ +left: this.activatorOffset.left + this.activatorOffset.width +}), this.addRemoveClass("left", !0)) : (this.applyPosition({ +left: this.activatorOffset.left - e.width +}), this.addRemoveClass("right", !0)) : this.activatorOffset.left - e.width > 0 ? (this.applyPosition({ +left: this.activatorOffset.left - e.left - e.width +}), this.addRemoveClass("right", !0)) : (this.applyPosition({ +left: this.activatorOffset.width +}), this.addRemoveClass("left", !0)), this.addRemoveClass("horizontal", !0), e = this.getBoundingRect(this.node), e.left < 0 || e.left + e.width > t ? !1 : !0; +}, +applyHorizontalPositioning: function() { +if (!this.initHorizontalPositioning()) return !1; +var e = this.getBoundingRect(this.node), t = this.getViewHeight(), n = this.activatorOffset.top + this.activatorOffset.height / 2; +return this.floating ? n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 - e.height / 2, +bottom: "auto" +}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ +top: this.activatorOffset.top - this.activatorOffset.height, +bottom: "auto" +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: this.activatorOffset.top - e.height + this.activatorOffset.height * 2, +bottom: "auto" +}), this.addRemoveClass("low", !0)) : n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ +top: (this.activatorOffset.height - e.height) / 2 +}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ +top: -this.activatorOffset.height +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: e.top - e.height - this.activatorOffset.top + this.activatorOffset.height +}), this.addRemoveClass("low", !0)), !0; +}, +applyHorizontalFlushPositioning: function(e, t) { +if (!this.initHorizontalPositioning()) return !1; +var n = this.getBoundingRect(this.node), r = this.getViewWidth(); +return this.floating ? this.activatorOffset.top < innerHeight / 2 ? (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 +}), this.addRemoveClass("high", !0)) : (this.applyPosition({ +top: this.activatorOffset.top + this.activatorOffset.height / 2 - n.height +}), this.addRemoveClass("low", !0)) : n.top + n.height > innerHeight && innerHeight - n.bottom < n.top - n.height ? (this.applyPosition({ +top: n.top - n.height - this.activatorOffset.top - this.activatorOffset.height / 2 +}), this.addRemoveClass("low", !0)) : (this.applyPosition({ +top: this.activatorOffset.height / 2 +}), this.addRemoveClass("high", !0)), this.activatorOffset.left + this.activatorOffset.width < e ? (this.addClass("left"), this.addClass("corner"), !0) : this.activatorOffset.left > t ? (this.addClass("right"), this.addClass("corner"), !0) : !1; +}, +getBoundingRect: function(e) { +var t = e.getBoundingClientRect(); +return !t.width || !t.height ? { +left: t.left, +right: t.right, +top: t.top, +bottom: t.bottom, +width: t.right - t.left, +height: t.bottom - t.top +} : t; +}, +getViewHeight: function() { +return window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight; +}, +getViewWidth: function() { +return window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; +}, +resetPositioning: function() { +this.removeClass("right"), this.removeClass("left"), this.removeClass("high"), this.removeClass("low"), this.removeClass("corner"), this.removeClass("below"), this.removeClass("above"), this.removeClass("vertical"), this.removeClass("horizontal"), this.applyPosition({ +left: "auto" +}), this.applyPosition({ +top: "auto" +}); +}, +resizeHandler: function() { +this.inherited(arguments), this.adjustPosition(); +}, +requestHide: function() { +this.setShowing(!1); +} +}); + +// App.js + +enyo.kind({ +name: "App", +kind: "FittableRows", +fit: !0, +components: [ { +kind: "onyx.Toolbar", +content: "Hello World" +}, { +kind: "enyo.Scroller", +fit: !0, +components: [ { +name: "main", +classes: "nice-padding", +allowHtml: !0 +} ] +}, { +kind: "onyx.Toolbar", +components: [ { +kind: "onyx.Button", +content: "Tap me", +ontap: "helloWorldTap" +} ] +} ], +helloWorldTap: function(e, t) { +this.$.main.addContent("The button was tapped.
    "); +} +}); diff --git a/deploy/bootplate/build/enyo.css b/deploy/bootplate/build/enyo.css new file mode 100644 index 0000000..6d05291 --- /dev/null +++ b/deploy/bootplate/build/enyo.css @@ -0,0 +1,181 @@ + +/* ../source/dom/dom.css */ + +/* things we always want */ +body { + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; +} + +/* allow hw-accelerated scrolling on platforms that support it */ +body.webkitOverflowScrolling { + -webkit-overflow-scrolling: touch; +} + +/* for apps */ +.enyo-document-fit { + margin: 0; + height: 100%; + /* note: giving html overflow: auto is odd and was only ever done to avoid duplication + however, android 4.04 sometimes does not hide nodes when their display is set to none + if document is overflow auto. + */ + position: relative; +} + +.enyo-body-fit { + margin: 0; + height: 100%; + /* helps prevent ios page scroll */ + overflow: auto; + position: relative; +} + +.enyo-no-touch-action { + -ms-touch-action: none; +} + +/* reset */ + +button { + font-size: inherit; + font-family: inherit; +} +button::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* user selection */ + +.enyo-unselectable { + cursor: default; + -ms-user-select: none; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; +} + +.enyo-unselectable::selection, .enyo-unselectable ::selection { + color: transparent; +} + +.enyo-selectable { + cursor: auto; + -ms-user-select: element; + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; +} + +.enyo-selectable::selection, .enyo-selectable ::selection { + background: #3297FD; + color: #FFF; +} + +/* layout */ + +body .enyo-fit { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.enyo-clip { + overflow: hidden; +} + +.enyo-border-box { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* compositing */ + +.enyo-composite { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); +} + + +/* ../source/touch/Thumb.css */ + +.enyo-thumb { + position: absolute; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; + background: #333; + border: 1px solid #666; + opacity: 0.75; + z-index: 1; +} + +.enyo-vthumb { + top: 0; + right: 2px; + width: 4px; +} + +.enyo-hthumb { + left: 0; + bottom: 2px; + height: 4px; +} + + +/* ../source/touch/Scroller.css */ + +.enyo-scroller { + position: relative; +} + +.enyo-fit.enyo-scroller { + position: absolute; +} + +.enyo-touch-scroller { + overflow: hidden; +} + +.enyo-touch-strategy-container { + overflow: hidden; +} + +.enyo-scrollee-fit { + height: 100%; +} + +/* ../source/ui/ui.css */ + +.enyo-inline, .enyo-tool-decorator { + display: inline-block; +} + +.enyo-children-inline > *, .enyo-tool-decorator > * { + display: inline-block; +} + +.enyo-children-middle > *, .enyo-tool-decorator > * { + vertical-align: middle; +} + +.enyo-positioned { + position: relative; +} + +.enyo-fill { + position: relative; + width: 100%; + height: 100%; +} + +.enyo-popup { + position: absolute; + z-index: 10; +} diff --git a/deploy/bootplate/build/enyo.js b/deploy/bootplate/build/enyo.js new file mode 100644 index 0000000..e565f50 --- /dev/null +++ b/deploy/bootplate/build/enyo.js @@ -0,0 +1,4283 @@ + +// enyo.js + +(function() { +var e = "enyo.js"; +enyo = window.enyo || {}, enyo.locateScript = function(e) { +var t = document.getElementsByTagName("script"); +for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { +i = r.getAttribute("src") || ""; +if (i.slice(-s) == e) return r.located = !0, { +path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), +node: r +}; +} +}, enyo.args = enyo.args || {}; +var t = enyo.locateScript(e); +if (t) { +enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); +for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; +} +})(); + +// ../../loader.js + +(function() { +enyo = window.enyo || {}, enyo.pathResolverFactory = function() { +this.paths = {}; +}, enyo.pathResolverFactory.prototype = { +addPath: function(e, t) { +return this.paths[e] = t; +}, +addPaths: function(e) { +if (e) for (var t in e) this.addPath(t, e[t]); +}, +includeTrailingSlash: function(e) { +return e && e.slice(-1) !== "/" ? e + "/" : e; +}, +rewritePattern: /\$([^\/\\]*)(\/)?/g, +rewrite: function(e) { +var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { +return t = !0, n(r[i]) || ""; +}, s = e; +do t = !1, s = s.replace(this.rewritePattern, i); while (t); +return s; +} +}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { +this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; +}, enyo.loaderFactory.prototype = { +verbose: !1, +loadScript: function(e) { +this.machine.script(e); +}, +loadSheet: function(e) { +this.machine.sheet(e); +}, +loadPackage: function(e) { +this.machine.script(e); +}, +report: function() {}, +load: function() { +this.more({ +index: 0, +depends: arguments || [] +}); +}, +more: function(e) { +if (e && this.continueBlock(e)) return; +var t = this.stack.pop(); +t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); +}, +finish: function() { +this.packageFolder = "", this.verbose && console.log("-------------- fini"); +for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); +}, +continueBlock: function(e) { +while (e.index < e.depends.length) { +var t = e.depends[e.index++]; +if (t) if (typeof t == "string") { +if (this.require(t, e)) return !0; +} else this.pathResolver.addPaths(t); +} +}, +require: function(e, t) { +var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); +n = r + n; +if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { +if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; +this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); +} +}, +getPathPrefix: function(e) { +var t = e.slice(0, 1); +return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; +}, +requireStylesheet: function(e) { +this.sheets.push(e), this.loadSheet(e); +}, +requireScript: function(e, t) { +this.modules.push({ +packageName: this.packageName, +rawPath: e, +path: t +}), this.loadScript(t); +}, +decodePackagePath: function(e) { +var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; +if (s.length) { +var a = s.pop() || s.pop() || ""; +a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; +for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { +s.splice(o, 1); +break; +} +n = s.join("/"); +for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { +s = s.slice(o + 1); +break; +} +for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); +t = s.join("-"); +} +return { +alias: t, +target: n, +folder: r, +manifest: i +}; +}, +aliasPackage: function(e) { +var t = this.decodePackagePath(e); +this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ +name: t.alias, +folder: t.folder +})), this.packageFolder = t.folder; +}, +requirePackage: function(e, t) { +t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); +} +}; +})(); + +// boot.js + +enyo.execUnsafeLocalFunction = function(e) { +typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); +}, enyo.machine = { +sheet: function(e) { +var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; +r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); +var i; +enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { +document.write(''); +}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { +less.refresh(!0); +})); +}, +script: function(e, t, n) { +if (!enyo.runtimeLoading) document.write(' + + + + + + diff --git a/deploy/bootplate/lib/onyx/LICENSE-2.0.txt b/deploy/bootplate/lib/onyx/LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/deploy/bootplate/lib/onyx/LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/deploy/bootplate/lib/onyx/images/checkbox.png b/deploy/bootplate/lib/onyx/images/checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..9176591af4192b5f8fc9d1f66f77da078ae4ab5d GIT binary patch literal 5462 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 KMNUMnLSTZHmo(J? literal 0 HcmV?d00001 diff --git a/deploy/bootplate/lib/onyx/images/gradient-invert.png b/deploy/bootplate/lib/onyx/images/gradient-invert.png new file mode 100644 index 0000000000000000000000000000000000000000..44ab5ac084b0962fb8d709e84f158ec880744e6e GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<7!3HE7BzD~bQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F5`$3q|f;CtLC@59p8c`CQpH@h~YuU)o|cQ6aCV1LzC}Pgg&ebxsLQ0EN_9@c;k- literal 0 HcmV?d00001 diff --git a/deploy/bootplate/lib/onyx/images/gradient.png b/deploy/bootplate/lib/onyx/images/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..58562587c62b21c388f8957ad6e0370dba70487b GIT binary patch literal 255 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 literal 0 HcmV?d00001 diff --git a/deploy/bootplate/lib/onyx/images/search-input-cancel.png b/deploy/bootplate/lib/onyx/images/search-input-cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..8056b4a471e0a7da1e438c7d5cc9ef3a9862a813 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{doXXw8qoL zF~q|E?c{^J2NXD5_m;K2ySQ}j!6UXlF-xDC&r)DrS?=4Bc~t#_V$0s79`;Bj?UdzV zf`9U#f3RK_n!RCm*$wtn33t^i9UOLjW(ZBNST85=GK95iYsb&z55cF6Y%VEH4B)F$ z{>}P2g?$%Wa=;Qz<-^~%+VHnAEc;d8GBNA4$633pEE5f`_ypfX~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/deploy/bootplate/lib/onyx/images/slider-handle.png b/deploy/bootplate/lib/onyx/images/slider-handle.png new file mode 100644 index 0000000000000000000000000000000000000000..09e12fbd19e1ff9e3faef8f2a2baaffab78688ae GIT binary patch literal 3095 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 Pn1F;$An(;T&^-PCGf5vc literal 0 HcmV?d00001 diff --git a/enyo/CONTRIBUTING md b/enyo/CONTRIBUTING md new file mode 100644 index 0000000..e191d77 --- /dev/null +++ b/enyo/CONTRIBUTING md @@ -0,0 +1,10 @@ +# Contributions + +Contributions are welcome for Enyo and its associated libraries including onyx and layout. + +Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details +on our contribution policy and guidelines for use of the Enyo-DCO-1.1-Signed-off-by +line in your commits and pull requests. + +If you're interested in introducing new kinds, you might also consider hosting your own repo +and contributing to the [Enyo community gallery](http://enyojs.com/gallery). \ No newline at end of file diff --git a/enyo/LICENSE-2.0.txt b/enyo/LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/enyo/LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/enyo/README.md b/enyo/README.md new file mode 100644 index 0000000..fef69dc --- /dev/null +++ b/enyo/README.md @@ -0,0 +1,146 @@ +### Looking for the issue tracker? +It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). + +--- + +# Quick Info + +## Core + +This repository contains Enyo core. We've pared it down to the essentials, so folks can work at the metal. Widget libraries, g11n code, and other fancy bits are optional packages. + +## Lib + +Packages should go in a folder named _lib_ (e.g. the _extra_ or _canvas_ repositories on GitHub). _lib_ is a magic name that enyo uses to work with add-on packages. It's recommended you create a _lib_ folder as sibling to _enyo_ and keep your packages there, but you can make as many _lib_ folders as you like and put them anywhere. + +## Warning about file:// + +_Note_: in Chrome, various samples will not work from file:// because of Chrome's security policy. Run from a local http server, use the --allow-file-access-from-files in Chrome, or use the online versions at http://enyojs.com. + +# What Is Enyo + +Enyo is an object-oriented JavaScript application framework emphasizing modularity and encapsulation. Enyo is suitable for small and large-scale applications. + +Enyo up to 1.x was the underlying framework used to develop applications for HP's TouchPad tablet. Enyo as shipped on the TouchPad included an complete set of user interface components and service wrappers. What you will find here is Enyo 2, what we informally call _core_: the primary infrastructure needed to support any number of Enyo-based libraries. Not to worry, Enyo 1.x itself is open-source licensed, and work is progressing on packaging up those controls and goodies to work with Enyo 2. + +Enyo was designed from the beginning to be highly extensible. This repository reflects a small working set of code, that can be expanded with any number of libraries or plugins. + +Enyo 2 is lightweight, easy to digest, and powerful. + +# What Do I Get + +The core code includes the Enyo kernel, the DOM extensions, some Ajax (XHR) tools, and basic wrapper kinds for a lot of DOM form elements. These things are actually separable (it's easy to make micro-builds of Enyo), but we believe this is a useful working set. + +The Enyo 2 kernel provides a modularity concept (Component) and a view concept (UiComponent). The DOM aspect includes a widget concept (Control) and an extensible event system (Dispatcher). The Ajax package includes basic xhr functionality and an implementation of xhr as a Component (Ajax). The touch package provides platform-optimized scrollers, while the UI package provides base kinds for common controls like buttons and popups. + +Just these pieces are sufficient to create large applications using the Enyo encapsulation model. Developers that want only this low-level code are encouraged to roll-their-own. For those that want a richer set of tools, there are some pre-built libraries already available, and much more on the way. + +# Why Do I Care + +First is our emphasis on cross-platform: Enyo core works on both desktop and mobile browsers. + +Second is Enyo's building block approach to applications. Each piece of an application is a Component, and Components are constructed out of other Components. + +For example, it's easy to define a combination of an `` tag with a `

    Hello From Enyo
    +``` + +Now, the good parts start when you combine more than one Control, e.g. + +```javascript +new enyo.Control({ + components: [ + {content: "Hello From Enyo"}, + {tag: "hr"} + ] +}).renderInto(document.body); +``` + +This Control now encapsulates two Controls into one scope (we can encapsulate any type of Component, that's why the property is called _components_. Controls are one kind of Component.) The outer Control is responsible for the encapsulated components: it manages their lifecycle, listens to their messages, and maintains references to them. For example: + +```javascript +new enyo.Control({ + components: [ + {name: "hello", content: "Hello From Enyo", ontap: "helloTap"}, + {tag: "hr"} + ], + helloTap: function() { + this.$.hello.addStyles("color: red"); + } +}).renderInto(document.body); +``` + +Here we've given one of the components a name ('hello') and told it to send a 'helloTap' message when it's tapped (tap is basically the same as the DOM click event, but it works in both mouse and touch environments). The '$' property is a hash that references all the sub-components (we don't store these references directly on _this_ to avoid name conflicts). Notice there is no add/remove machinery to listen to this event, that's all taken care of. + +The main point is that 'hello' and the 'hr', their references and behavior, are completely contained inside the outer control. Now, to re-use this, we need to make it a prototype. + +Enyo contains a constructor/prototype-generator that we call enyo.kind. Constructors that enyo.kind produces are called _kinds_. Kinds are not magic, they are just regular old JavaScript constructors. Using the enyo.kind factory however allows us to remove boilerplate from our prototype generation (DRY) and have compact syntax. We can convert the Control above to a kind like so: + +```javascript +enyo.kind({ + name: "Hello", + kind: enyo.Control, + components: [ + {name: "hello", content: "Hello From Enyo", ontap: "helloTap"}, + {tag: "hr"} + ], + helloTap: function() { + this.$.hello.addStyles("color: red"); + } +}); +// make two, they're small +new enyo.Control({ + component: [ {kind: "Hello"}, {kind: "Hello"} ] + }).renderInto(document.body); +``` + +The code above creates a new kind called "Hello" derived from enyo.Control. It contains some components and some behavior. I can create as many "Hello" objects as I want, each instance is independent, and the user of a "Hello" doesn't need to know anything about its internals. + +This ability to define encapsulated objects and behavior (Components) and to re-use those encapsulations as prototypes (kinds) is money. diff --git a/enyo/enyo.js b/enyo/enyo.js new file mode 100644 index 0000000..596eae7 --- /dev/null +++ b/enyo/enyo.js @@ -0,0 +1,41 @@ +(function() { + // enyo can use information from the script tag that loads this bootstrap file + var thisScript = "enyo.js"; + + enyo = window.enyo || {}; + + enyo.locateScript = function(inName) { + var scripts = document.getElementsByTagName("script"); + for (var i=scripts.length-1, s, src, l=inName.length; (i>=0) && (s=scripts[i]); i--) { + if (!s.located) { + src = s.getAttribute("src") || ""; + if (src.slice(-l) == inName) { + s.located = true; + return {path: src.slice(0, Math.max(0, src.lastIndexOf("/"))), node: s}; + } + } + } + }; + + enyo.args = enyo.args || {}; + + var tag = enyo.locateScript(thisScript); + if (tag) { + // infer the framework path from the document, unless the user has specified one explicitly + enyo.args.root = (enyo.args.root || tag.path); + // all attributes of the bootstrap script tag become enyo.args + for (var i=0, al = tag.node.attributes.length, it; (i < al) && (it = tag.node.attributes.item(i)); i++) { + enyo.args[it.nodeName] = it.value; + } + } + + var root = enyo.args.root; + + var script = function(inSrc) { + document.write(''); + }; + + script("../../loader.js"); + script("boot.js"); + script("../package.js"); +})(); diff --git a/enyo/loader.js b/enyo/loader.js new file mode 100644 index 0000000..931c8da --- /dev/null +++ b/enyo/loader.js @@ -0,0 +1,302 @@ +(function() { + enyo = window.enyo || {}; + + enyo.pathResolverFactory = function() { + this.paths = {}; + }; + + enyo.pathResolverFactory.prototype = { + addPath: function(inName, inPath) { + return this.paths[inName] = inPath; + }, + addPaths: function(inPaths) { + if (inPaths) { + for (var n in inPaths) { + this.addPath(n, inPaths[n]); + } + } + }, + includeTrailingSlash: function(inPath) { + return (inPath && inPath.slice(-1) !== "/") ? inPath + "/" : inPath; + }, + // match $name + rewritePattern: /\$([^\/\\]*)(\/)?/g, + // replace macros of the form $pathname with the mapped value of paths.pathname + rewrite: function (inPath) { + var working, its = this.includeTrailingSlash, paths = this.paths; + var fn = function(macro, name) { + working = true; + return its(paths[name]) || ''; + }; + var result = inPath; + do { + working = false; + result = result.replace(this.rewritePattern, fn); + } while (working); + return result; + } + }; + + enyo.path = new enyo.pathResolverFactory(); + + enyo.loaderFactory = function(inMachine, inPathResolver) { + this.machine = inMachine; + // package information + this.packages = []; + // module information + this.modules = []; + // stylesheet paths + this.sheets = []; + // (protected) internal dependency stack + this.stack = []; + this.pathResolver = inPathResolver || enyo.path; + this.packageName = ""; + this.packageFolder = ""; + this.finishCallbacks = {}; + }; + + enyo.loaderFactory.prototype = { + verbose: false, + loadScript: function(inScript) { + this.machine.script(inScript); + }, + loadSheet: function(inSheet) { + this.machine.sheet(inSheet); + }, + loadPackage: function(inPackage) { + this.machine.script(inPackage); + }, + report: function() { + }, + // + load: function(/**/) { + // begin processing dependencies + this.more({ + index: 0, + depends: arguments || [] + }); + }, + more: function(inBlock) { + // a 'block' is a dependency list with a bookmark + // the bookmark (index) allows us to interrupt + // processing and then continue asynchronously. + if (inBlock) { + // returns true if this block has asynchronous requirements + // in that case, we unwind the stack. The asynchronous loader + // must provide the continuation (by calling 'more' again). + if (this.continueBlock(inBlock)) { + return; + } + } + // A package is now complete. Pop the block that was interrupted for that package (if any). + var block = this.stack.pop(); + if (block) { + // block.packageName is the name of the package that interrupted us + //this.report("finished package", block.packageName); + if (this.verbose) { + console.groupEnd("* finish package (" + (block.packageName || "anon") + ")"); + } + // cache the folder for the currently processing package + this.packageFolder = block.folder; + // no current package + this.packageName = ""; + // process this new block + this.more(block); + } else { + this.finish(); + } + }, + finish: function() { + this.packageFolder = ""; + if (this.verbose) { + console.log("-------------- fini"); + } + for (var i in this.finishCallbacks) { + if (this.finishCallbacks[i]) { + this.finishCallbacks[i](); + this.finishCallbacks[i] = null; + } + } + }, + continueBlock: function(inBlock) { + while (inBlock.index < inBlock.depends.length) { + var d = inBlock.depends[inBlock.index++]; + if (d) { + if (typeof d == "string") { + if (this.require(d, inBlock)) { + // return true to indicate we need to interrupt + // processing until asynchronous file load completes + // the load process itself must provide the + // continuation + return true; + } + } else { + this.pathResolver.addPaths(d); + } + } + } + }, + require: function(inPath, inBlock) { + // process aliases + var path = this.pathResolver.rewrite(inPath); + // get path root + var prefix = this.getPathPrefix(inPath); + // assemble path + path = prefix + path; + // process path + if ((path.slice(-4) == ".css") || (path.slice(-5) == ".less")) { + if (this.verbose) { + console.log("+ stylesheet: [" + prefix + "][" + inPath + "]"); + } + this.requireStylesheet(path); + } else if (path.slice(-3) == ".js" && path.slice(-10) != "package.js") { + if (this.verbose) { + console.log("+ module: [" + prefix + "][" + inPath + "]"); + } + this.requireScript(inPath, path); + } else { + // package + this.requirePackage(path, inBlock); + // return true to indicate a package was located and + // we need to interrupt further processing until it's completed + return true; + } + }, + getPathPrefix: function(inPath) { + var delim = inPath.slice(0, 1); + if ((delim != "/") && (delim != "\\") && (delim != "$") && !/^https?:/i.test(inPath)) { + return this.packageFolder; + } + return ""; + }, + requireStylesheet: function(inPath) { + // stylesheet + this.sheets.push(inPath); + this.loadSheet(inPath); + }, + requireScript: function(inRawPath, inPath) { + // script file + this.modules.push({ + packageName: this.packageName, + rawPath: inRawPath, + path: inPath + }); + this.loadScript(inPath); + }, + decodePackagePath: function(inPath) { + // A package path can be encoded in two ways: + // + // 1. [folder] + // 2. [folder]/[*package.js] + // + // Note: manifest file name must end in "package.js" + // + var alias = '', target = '', folder = '', manifest = 'package.js'; + // convert back slashes to forward slashes, remove double slashes, split on slash + var parts = inPath.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"); + var i, p; + if (parts.length) { + // if inPath has a trailing slash, parts has an empty string which we pop off and ignore + var name = parts.pop() || parts.pop() || ""; + // test if name includes the manifest tag + if (name.slice(-manifest.length) !== manifest) { + // if not a manifest name, it's part of the folder path + parts.push(name); + } else { + // otherwise this is the manifest name + manifest = name; + } + // + folder = parts.join("/"); + folder = (folder ? folder + "/" : ""); + manifest = folder + manifest; + // + // build friendly aliasing: + // + for (i=parts.length-1; i >= 0; i--) { + if (parts[i] == "source") { + parts.splice(i, 1); + break; + } + } + target = parts.join("/"); + // + // portable aliasing: + // + // packages that are rooted at a folder named "enyo" or "lib" do not + // include that root path in their alias + // + // remove */lib or */enyo prefix + // + // e.g. foo/bar/baz/lib/zot -> zot package + // + for (i=parts.length-1; (p=parts[i]); i--) { + if (p == "lib" || p == "enyo") { + parts = parts.slice(i+1); + break; + } + } + // remove ".." and "." + for (i=parts.length-1; (p=parts[i]); i--) { + if (p == ".." || p == ".") { + parts.splice(i, 1); + } + } + // + alias = parts.join("-"); + } + return { + alias: alias, + target: target, + folder: folder, + manifest: manifest + }; + }, + aliasPackage: function(inPath) { + var parts = this.decodePackagePath(inPath); + // cache manifest path + this.manifest = parts.manifest; + // cache package info for named packages + if (parts.alias) { + // debug only + /* + var old = this.pathResolver.paths[parts.name]; + if (old && old != parts.folder) { + this.verbose && console.warn("mapping alias [" + parts.name + "] to [" + parts.folder + "] replacing [" + old + "]"); + } + this.verbose && console.log("mapping alias [" + parts.name + "] to [" + parts.folder + "]"); + */ + // + // create a path alias for this package + this.pathResolver.addPath(parts.alias, parts.target); + // + // cache current name + this.packageName = parts.alias; + // cache package information + this.packages.push({ + name: parts.alias, + folder: parts.folder + }); + } + // cache current folder + this.packageFolder = parts.folder; + }, + requirePackage: function(inPath, inBlock) { + // cache the interrupted packageFolder + inBlock.folder = this.packageFolder; + this.aliasPackage(inPath); + // cache the name of the package 'inBlock' is loading now + inBlock.packageName = this.packageName; + // push inBlock on the continuation stack + this.stack.push(inBlock); + // console/user reporting + this.report("loading package", this.packageName); + if (this.verbose) { + console.group("* start package [" + this.packageName + "]"); + } + // load the actual package. the package MUST call a continuation function + // or the process will halt. + this.loadPackage(this.manifest); + } + }; +})(); \ No newline at end of file diff --git a/enyo/minify/minify.bat b/enyo/minify/minify.bat new file mode 100644 index 0000000..2c42a20 --- /dev/null +++ b/enyo/minify/minify.bat @@ -0,0 +1,6 @@ +@ECHO OFF +REM FIXME: minify has a problem if 'package.js' is not in CWD, hence push, cd, pop +PUSHD "%CD%" +CD "%~dp0" +CALL ..\tools\minify.bat package.js -no-alias -output ..\..\build\enyo %* +POPD diff --git a/enyo/minify/minify.sh b/enyo/minify/minify.sh new file mode 100644 index 0000000..ca409c8 --- /dev/null +++ b/enyo/minify/minify.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cd $(dirname $0) +../tools/minify.sh package.js -no-alias -output ../../build/enyo diff --git a/enyo/minify/package.js b/enyo/minify/package.js new file mode 100644 index 0000000..02ba830 --- /dev/null +++ b/enyo/minify/package.js @@ -0,0 +1,4 @@ +enyo.depends( + "../source/boot", + "../source" +); diff --git a/enyo/package.json b/enyo/package.json new file mode 100644 index 0000000..594d4d3 --- /dev/null +++ b/enyo/package.json @@ -0,0 +1,19 @@ +{ + "name": "enyo", + "filename": "enyo.js", + "version": "2.2.0", + "description":"Enyo is an open source object-oriented JavaScript framework emphasizing encapsulation and modularity. Enyo contains everything you need to create a fast, scalable mobile or web application.", + "homepage": "http://enyojs.com/", + "keywords": [ "framework", "toolkit", "components", "mobile", "webOS" ], + "maintainers": [{ + "name": "Enyo JS Framework Team (HP)", + "web": "http://enyojs.com/" + }], + "licenses": [{ + "type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" + }], + "bugs": "https://jira.enyojs.com/", + "repositories": [{ + "type": "git", "url": "http://github.com/enyojs/enyo" + }] +} diff --git a/enyo/samples/AjaxSample.css b/enyo/samples/AjaxSample.css new file mode 100644 index 0000000..850c658 --- /dev/null +++ b/enyo/samples/AjaxSample.css @@ -0,0 +1,14 @@ +.ajax-sample { + padding: 15px; +} + +.ajax-sample-source { + padding:15px; + font-family: monospace; + font-size: 12px; + white-space: pre-wrap; + box-sizing: border-box; + width:100%; + height:100%; + margin-top:15px; +} diff --git a/enyo/samples/AjaxSample.html b/enyo/samples/AjaxSample.html new file mode 100644 index 0000000..7a3a758 --- /dev/null +++ b/enyo/samples/AjaxSample.html @@ -0,0 +1,21 @@ + + + + AJAX Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/AjaxSample.js b/enyo/samples/AjaxSample.js new file mode 100644 index 0000000..d04d972 --- /dev/null +++ b/enyo/samples/AjaxSample.js @@ -0,0 +1,37 @@ +enyo.kind({ + name: "enyo.sample.AjaxSample", + kind: "FittableRows", + classes: "enyo-fit ajax-sample", + components: [ + {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ + {content: "YQL: "}, + {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, + {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} + ]}, + {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ + {content: "URL: "}, + {kind: "onyx.Input", name:"baseUrl", fit:true, value:'http://query.yahooapis.com/v1/public/yql?format=json'} + ]}, + {kind: "onyx.TextArea", fit:true, classes:"ajax-sample-source"} + ], + fetch: function() { + var ajax = new enyo.Ajax({ + url: this.$.baseUrl.getValue() + }); + // send parameters the remote service using the 'go()' method + ajax.go({ + q: this.$.query.getValue() + }); + // attach responders to the transaction object + ajax.response(this, "processResponse"); + // handle error + ajax.error(this, "processError"); + }, + processResponse: function(inSender, inResponse) { + // do something with it + this.$.textArea.setValue(JSON.stringify(inResponse, null, 2)); + }, + processError: function(inSender, inResponse) { + alert("Error!"); + } +}); \ No newline at end of file diff --git a/enyo/samples/GestureSample.css b/enyo/samples/GestureSample.css new file mode 100644 index 0000000..bdf6c08 --- /dev/null +++ b/enyo/samples/GestureSample.css @@ -0,0 +1,57 @@ +.gesture-sample { + padding: 15px; +} + +.gesture-sample > * { + margin-bottom:10px; +} + +.gesture-sample-pad { + border-radius: 5px; + background-color: #888; + color: #686868; + text-shadow:#AAA 0px 1px 0, #000 0 -1px 0; + text-align:center; + padding-top:15%; + font-size:30px; + overflow:hidden; +} + +.gesture-sample-note { + font-size:15px; + text-shadow:none; +} + +.gesture-sample-padded > * { + padding:5px; +} + +.gesture-sample-left > * { + text-align:left; +} + +.gesture-sample-setting { + font-size: 15px; + padding: 10px; + min-height: 30px; + line-height: 30px; +} +.gesture-sample-setting > * { + display: inline-block; +} + +.gesture-sample-setting > :last-child { + float: right; +} + +@media all and (max-height:600px) { + .gesture-sample-truncate { + width:100%; + word-wrap:normal; + white-space:nowrap; + overflow:hidden; + -o-text-overflow:ellipsis; + text-overflow:ellipsis; + } +} + diff --git a/enyo/samples/GestureSample.html b/enyo/samples/GestureSample.html new file mode 100644 index 0000000..544ee8e --- /dev/null +++ b/enyo/samples/GestureSample.html @@ -0,0 +1,21 @@ + + + + Gesture Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/GestureSample.js b/enyo/samples/GestureSample.js new file mode 100644 index 0000000..6a64b27 --- /dev/null +++ b/enyo/samples/GestureSample.js @@ -0,0 +1,198 @@ +enyo.kind({ + name: "enyo.sample.GestureSample", + kind: "FittableRows", + classes: "gesture-sample enyo-fit enyo-unselectable", + components: [ + { + classes:"gesture-sample-pad", + fit:true, + ondown: "handleEvent", + onup: "handleEvent", + ontap: "handleEvent", + onmove: "handleEvent", + onenter: "handleEvent", + onleave: "handleEvent", + ondragstart: "handleEvent", + ondrag: "handleEvent", + ondragover: "handleEvent", + onhold: "handleEvent", + onrelease: "handleEvent", + onholdpulse: "handleEvent", + onflick: "handleEvent", + ongesturestart: "handleEvent", + ongesturechange: "handleEvent", + ongestureend: "handleEvent", + components: [ + {content: "Perform gestures here"}, + {classes: "gesture-sample-note", content:"(tap below for options)"} + ] + }, + {kind: "onyx.Groupbox", ontap:"toggleSettings", components: [ + {kind: "onyx.GroupboxHeader", content: "Events"}, + {name: "eventList", style:"font-size:12px;", onDone:"removeEvent", components: [ + {name:"waiting", content: "Waiting for events...", style:"padding:4px;font-style:italic;color:gray;"} + ]} + ]}, + {ontap:"toggleSettings", name:"settings", showing:false, components: [ + {kind: "onyx.Groupbox", classes:"gesture-sample-padded", components: [ + {kind: "onyx.GroupboxHeader", content: "Options"}, + {classes:"gesture-sample-setting", components: [ + {content:"Truncate detail on small screen: "}, + {name:"truncateDetail", onchange:"truncateChanged", ontap:"preventDefault", kind:"onyx.Checkbox", checked:true} + ]}, + {classes:"gesture-sample-setting", style:"min-height:40px;", components: [ + {content:"Monitor event: "}, + {kind:"onyx.PickerDecorator", ontap:"preventDefault", onSelect:"monitorEventSelected", components: [ + {content:"Select event", style:"width:140px; margin-bottom:5px;"}, + {name:"eventPicker", kind:"onyx.Picker", classes:"gesture-sample-left"} + ]} + ]} + ]} + ]} + ], + create: function() { + this.inherited(arguments); + this.eventList = {}; + this.eventCount = 0; + enyo.forEach(["All events","down","up","tap","move","enter","leave","dragstart","drag","dragover","hold","release","holdpulse","flick","gesturestart","gesturechange","gestureend"], enyo.bind(this, function(event) { + this.$.eventPicker.createComponent({content:event, style:"text-align:left"}); + })); + }, + handleEvent: function(inSender, inEvent) { + var event = enyo.clone(inEvent); + if (this.monitorEvent && (event.type != this.monitorEvent)) { + return true; + } + var eventItem = this.eventList[event.type]; + if (eventItem) { + eventItem.setEvent(event); + } else { + this.eventCount++; + eventItem = this.$.eventList.createComponent({ + kind: "enyo.sample.EventItem", + event:event, + truncate: this.$.truncateDetail.getValue(), + persist: this.monitorEvent + }); + this.eventList[event.type] = eventItem; + } + eventItem.render(); + this.$.waiting.hide(); + this.reflow(); + return true; + }, + truncateChanged: function() { + for (var i in this.eventList) { + this.eventList[i].setTruncate(this.$.truncateDetail.getValue()); + } + this.reflow(); + return false; + }, + removeEvent: function(inSender, inEvent) { + this.eventCount--; + this.eventList[inEvent.type].destroy(); + delete this.eventList[inEvent.type]; + if (this.eventCount === 0) { + this.$.waiting.show(); + } + this.reflow(); + return true; + }, + removeAllEvents: function() { + for (var i in this.eventList) { + this.eventList[i].destroy(); + delete this.eventList[i]; + } + this.eventCount = 0; + this.$.waiting.show(); + this.reflow(); + }, + toggleSettings: function() { + this.$.settings.setShowing(!this.$.settings.getShowing()); + this.reflow(); + }, + preventDefault: function() { + return true; + }, + monitorEventSelected: function(inSender, inEvent) { + this.removeAllEvents(); + if (inEvent.originator.content == "All events") { + this.monitorEvent = null; + } else { + this.monitorEvent = inEvent.originator.content; + } + } +}); + +enyo.kind({ + name:"enyo.sample.EventItem", + published: { + event:"", + truncate: true, + persist: false + }, + style:"padding:4px;", + events: { + onDone:"" + }, + components: [ + {name:"eventProps", allowHtml:true}, + {kind:"Animator", duration:1000, startValue:0, endValue:255, onStep:"stepAnimation", onEnd:"animationEnded"} + ], + create: function() { + this.inherited(arguments); + this.eventChanged(); + this.truncateChanged(); + }, + truncateChanged: function() { + this.$.eventProps.addRemoveClass("gesture-sample-truncate", this.truncate); + }, + // since event is an object, force set + setEvent: function(inEvent) { + this.setPropertyValue("event", inEvent, "eventChanged"); + }, + eventChanged: function(inOld) { + if (this.event) { + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.$.animator.stop(); + this.$.eventProps.setContent(this.getPropsString()); + this.$.animator.play(); + } + }, + stepAnimation: function(inSender, inEvent) { + var v = Math.floor(inSender.value); + this.applyStyle("background-color", "rgb(" + v + ",255," + v + ");"); + }, + animationEnded: function() { + if (!this.persist) { + this.timeout = setTimeout(enyo.bind(this, function() { + this.doDone({type:this.event.type}); + }), 2000); + } + }, + destroy: function() { + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.inherited(arguments); + }, + getPropsString: function() { + var props = []; + for (var i in this.event) { + if ((this.event[i] !== undefined) && + (this.event[i] !== null) && + !(this.event[i] instanceof Object) && + (i != "type")) { + props.push(i + ": " + this.event[i]); + } + } + if (this.event.srcEvent && this.event.srcEvent.type) { + props.push("srcEvent.type: " + this.event.srcEvent.type); + } + return "" + this.event.type + ": { " + props.join(", ") + " }"; + } +}); \ No newline at end of file diff --git a/enyo/samples/JsonpSample.css b/enyo/samples/JsonpSample.css new file mode 100644 index 0000000..7d9fab8 --- /dev/null +++ b/enyo/samples/JsonpSample.css @@ -0,0 +1,14 @@ +.jsonp-sample { + padding: 15px; +} + +.jsonp-sample-source { + padding:15px; + font-family: monospace; + font-size: 12px; + white-space: pre-wrap; + box-sizing: border-box; + width:100%; + height:100%; + margin-top:15px; +} diff --git a/enyo/samples/JsonpSample.html b/enyo/samples/JsonpSample.html new file mode 100644 index 0000000..de7e057 --- /dev/null +++ b/enyo/samples/JsonpSample.html @@ -0,0 +1,21 @@ + + + + JSON-P Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/JsonpSample.js b/enyo/samples/JsonpSample.js new file mode 100644 index 0000000..b7c8746 --- /dev/null +++ b/enyo/samples/JsonpSample.js @@ -0,0 +1,29 @@ +enyo.kind({ + name: "enyo.sample.JsonpSample", + kind: "FittableRows", + classes: "enyo-fit jsonp-sample", + components: [ + {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ + {content: "YQL: "}, + {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, + {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} + ]}, + {kind: "onyx.TextArea", fit:true, classes:"jsonp-sample-source"} + ], + fetch: function() { + var jsonp = new enyo.JsonpRequest({ + url: "http://query.yahooapis.com/v1/public/yql?format=json", + callbackName: "callback" + }); + // send parameters the remote service using the 'go()' method + jsonp.go({ + q: this.$.query.getValue() + }); + // attach responders to the transaction object + jsonp.response(this, "processResponse"); + }, + processResponse: function(inSender, inResponse) { + // do something with it + this.$.textArea.setValue(JSON.stringify(inResponse, null, 2)); + } +}); \ No newline at end of file diff --git a/enyo/samples/PlatformSample.css b/enyo/samples/PlatformSample.css new file mode 100644 index 0000000..326002e --- /dev/null +++ b/enyo/samples/PlatformSample.css @@ -0,0 +1,11 @@ +.platform-sample { + padding: 15px; +} +.platform-sample-divider { + color: #F49200; + text-transform: uppercase; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; + font-weight: bold; + margin-bottom: 8px; +} \ No newline at end of file diff --git a/enyo/samples/PlatformSample.html b/enyo/samples/PlatformSample.html new file mode 100644 index 0000000..e06115f --- /dev/null +++ b/enyo/samples/PlatformSample.html @@ -0,0 +1,21 @@ + + + + Platform Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/PlatformSample.js b/enyo/samples/PlatformSample.js new file mode 100644 index 0000000..389e6e9 --- /dev/null +++ b/enyo/samples/PlatformSample.js @@ -0,0 +1,36 @@ +enyo.kind({ + name: "enyo.sample.PlatformSample", + kind: "FittableRows", + classes: "enyo-fit platform-sample", + components: [ + {classes: "platform-sample-divider", content: "Enyo Platform Detection"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "User-Agent String"}, + {name: "uaString", content: "", style: "padding: 8px;"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "Window"}, + {name: "windowAttr", content: "", style: "padding: 8px;"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "enyo.platform"}, + {name: "enyoPlatformJSON", content: "", style: "padding: 8px;"} + ]} + ], + updateWindowSize: function() { + this.$.windowAttr.setContent("size: " + window.innerWidth + "x" + window.innerHeight + + ", devicePixelRatio: " + window.devicePixelRatio); + }, + create: function() { + this.inherited(arguments); + this.$.uaString.setContent(navigator.userAgent); + this.$.enyoPlatformJSON.setContent(JSON.stringify(enyo.platform, null, 1)); + this.updateWindowSize(); + }, + resizeHandler: function() { + this.inherited(arguments); + this.updateWindowSize(); + } +}); \ No newline at end of file diff --git a/enyo/samples/Playground.css b/enyo/samples/Playground.css new file mode 100644 index 0000000..bc8b4fd --- /dev/null +++ b/enyo/samples/Playground.css @@ -0,0 +1,29 @@ +.playground-sample-player { + padding: 15px; +} + +.playground-sample-source { + padding:15px; + font-family: monospace; + font-size: 12px; + white-space: pre-wrap; + box-sizing: border-box; + width:100%; + height:100%; +} + +.playground-sample-panels > * { + width:320px; + box-shadow: -4px 0px 4px rgba(0,0,0,0.3); + -moz-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); + -webkit-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); +} + +.sample-output { + min-height: 200px; + border: 1px solid black; + margin: 10px; + padding: 10px; + border-radius: 10px; + text-align: center; +} diff --git a/enyo/samples/Playground.html b/enyo/samples/Playground.html new file mode 100644 index 0000000..fb6b7a8 --- /dev/null +++ b/enyo/samples/Playground.html @@ -0,0 +1,23 @@ + + + + Enyo Playground + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/Playground.js b/enyo/samples/Playground.js new file mode 100644 index 0000000..970a0dc --- /dev/null +++ b/enyo/samples/Playground.js @@ -0,0 +1,54 @@ +enyo.kind({ + name: "enyo.sample.Playground", + kind: "Panels", + classes: "enyo-fit onyx playground-sample-panels", + arrangerKind:"CollapsingArranger", + components: [ + {kind: "FittableRows", style:"width:50%;", components: [ + {kind: "onyx.Toolbar", name:"toolbar", layoutKind:"FittableColumnsLayout", components: [ + {content: "Enyo Playground", fit:true}, + {kind: "onyx.PickerDecorator", components: [ + {}, + {kind: "onyx.Picker", floating:true, onChange:"sampleChanged", components: [ + {content:"Sample1", active:true}, + {content:"Sample2"}, + {content:"Sample3"}, + {content:"Sample4"} + ]} + ]} + ]}, + {fit:true, style:"padding:15px;", components: [ + {kind: "CodeEditor", fit:true, classes:"playground-sample-source"}, + ]}, + {kind: "FittableColumns", style:"margin:0px 15px 15px 15px", components: [ + {fit:true}, // spacer + {kind: "onyx.Button", content: "Render Kind", ontap: "go"} + ]} + ]}, + {kind: "FittableRows", classes:"onyx", components: [ + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Grabber"}, + {content: "Result"} + ]}, + {kind: "Scroller", fit:true, components: [ + {kind: "CodePlayer", fit:true, classes: "playground-sample-player"} + ]} + ]} + ], + create: function() { + this.inherited(arguments); + }, + sampleChanged: function(inSender, inEvent) { + this.loadSample(inEvent.selected.content); + this.$.toolbar.resized(); + }, + loadSample: function(inSample) { + this.$.codeEditor.setUrl("assets/" + inSample + ".js"); + }, + go: function() { + this.$.codePlayer.go(this.$.codeEditor.getValue()); + if (enyo.Panels.isScreenNarrow()) { + this.next(); + } + } +}); \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.css b/enyo/samples/RepeaterSample.css new file mode 100644 index 0000000..09ff891 --- /dev/null +++ b/enyo/samples/RepeaterSample.css @@ -0,0 +1,9 @@ +.repeater-sample { + padding:15px; +} +.repeater-sample-item { + padding:4px; + margin:2px; + border:1px solid gray; + background-color: lightgray; +} \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.html b/enyo/samples/RepeaterSample.html new file mode 100644 index 0000000..28d0328 --- /dev/null +++ b/enyo/samples/RepeaterSample.html @@ -0,0 +1,21 @@ + + + + Repeater Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.js b/enyo/samples/RepeaterSample.js new file mode 100644 index 0000000..732c45e --- /dev/null +++ b/enyo/samples/RepeaterSample.js @@ -0,0 +1,52 @@ +enyo.kind({ + name: "enyo.sample.RepeaterSample", + classes: "enyo-fit repeater-sample", + components: [ + {kind: "Repeater", onSetupItem:"setupItem", components: [ + {name:"item", classes:"repeater-sample-item", components: [ + {tag:"span", name: "personNumber"}, + {tag:"span", name: "personName"} + ]} + ]} + ], + create: function() { + this.inherited(arguments); + this.$.repeater.setCount(this.people.length); + }, + setupItem: function(inSender, inEvent) { + var index = inEvent.index; + var item = inEvent.item; + var person = this.people[index]; + item.$.personNumber.setContent((index+1) + ". "); + item.$.personName.setContent(person.name); + item.$.personName.applyStyle("color", person.sex == "male" ? "dodgerblue" : "deeppink"); + }, + people: [ + {name: "Andrew", sex:"male"}, + {name: "Betty", sex:"female"}, + {name: "Christopher", sex:"male"}, + {name: "Donna", sex:"female"}, + {name: "Ephraim", sex:"male"}, + {name: "Frankie", sex:"male"}, + {name: "Gerald", sex:"male"}, + {name: "Heather", sex:"female"}, + {name: "Ingred", sex:"female"}, + {name: "Jack", sex:"male"}, + {name: "Kevin", sex:"male"}, + {name: "Lucy", sex:"female"}, + {name: "Matthew", sex:"male"}, + {name: "Noreen", sex:"female"}, + {name: "Oscar", sex:"male"}, + {name: "Pedro", sex:"male"}, + {name: "Quentin", sex:"male"}, + {name: "Ralph", sex:"male"}, + {name: "Steven", sex:"male"}, + {name: "Tracy", sex:"female"}, + {name: "Uma", sex:"female"}, + {name: "Victor", sex:"male"}, + {name: "Wendy", sex:"female"}, + {name: "Xin", sex:"male"}, + {name: "Yulia", sex:"female"}, + {name: "Zoltan"} + ] +}); \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.css b/enyo/samples/ScrollerSample.css new file mode 100644 index 0000000..fef4aa7 --- /dev/null +++ b/enyo/samples/ScrollerSample.css @@ -0,0 +1,9 @@ +.scroller-sample-panels { + margin:15px; +} +.scroller-sample-content { + width:4000px; +} +.scroller-sample-scroller { + border: 1px solid orange; +} \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.html b/enyo/samples/ScrollerSample.html new file mode 100644 index 0000000..2360c11 --- /dev/null +++ b/enyo/samples/ScrollerSample.html @@ -0,0 +1,21 @@ + + + + Scroller Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.js b/enyo/samples/ScrollerSample.js new file mode 100644 index 0000000..b488d8a --- /dev/null +++ b/enyo/samples/ScrollerSample.js @@ -0,0 +1,78 @@ +enyo.kind({ + name: "enyo.sample.ScrollerSample", + kind: "FittableRows", + classes: "enyo-fit enyo-unselectable", + components: [ + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.PickerDecorator", components: [ + {content:"Choose Scroller", style:"width:250px;"}, + {kind: "onyx.Picker", floating:true, maxHeight: 300, onSelect:"sampleChanged", components: [ + {content:"Default scroller", active:true}, + {content:"Force touch scroller"}, + {content:"Horizontal only"}, + {content:"Vertical only"}, + {content:"Force TouchScrollStrategy"}, + {content:"Force TransitionScrollStrategy"}, + {content:"Force TranslateScrollStrategy"} + ]} + ]} + ]}, + {kind: "Panels", fit: true, draggable: false, classes: "scroller-sample-panels", components: [ + // Default scroller (chooses best scrolling method for platform) + {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit"}, + // Forces touch scrolling, even on desktop + {kind: "Scroller", touch:true, classes: "scroller-sample-scroller enyo-fit"}, + // Horizontal-only scrolling + {kind: "Scroller", vertical:"hidden", classes: "scroller-sample-scroller enyo-fit"}, + // Vertical-only scrolling + {kind: "Scroller", horizontal:"hidden", classes: "scroller-sample-scroller enyo-fit", onmousedown: "mouseDown", ondragstart: "dragStart"}, + // Force specific strategies + {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TouchScrollStrategy"}, + {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TransitionScrollStrategy"}, + {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TranslateScrollStrategy"} + ]} + ], + create: function() { + this.inherited(arguments); + var scrollers = this.$.panels.getPanels(); + for (var i in scrollers) { + scrollers[i].createComponent({ + allowHtml:true, + content:this.text, + classes:"scroller-sample-content" + }); + } + }, + sampleChanged: function(inSender, inEvent) { + this.$.panels.setIndex(inEvent.selected.indexInContainer()-1); + }, + text: "Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + + "Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow.
    Foo
    Bar
    Bar
    " + + "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + + "Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow.
    Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    " + + "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + + "Foo
    Bar
    Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow.
    Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    " + + "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + + "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow.
    ", + // The following are used when this sample is called from the Sampler app + mouseDown: function(inSender, inEvent) { + inEvent.preventDefault(); + }, + dragStart: function(inSender, inEvent) { + if (inEvent.horizontal) { + // Prevent drag propagation on horizontal drag events + return true; + } + } +}); \ No newline at end of file diff --git a/enyo/samples/WebServiceSample.css b/enyo/samples/WebServiceSample.css new file mode 100644 index 0000000..d63e5ba --- /dev/null +++ b/enyo/samples/WebServiceSample.css @@ -0,0 +1,14 @@ +.webservice-sample { + padding: 15px; +} + +.webservice-sample-source { + padding:15px; + font-family: monospace; + font-size: 12px; + white-space: pre-wrap; + box-sizing: border-box; + width:100%; + height:100%; + margin-top:15px; +} diff --git a/enyo/samples/WebServiceSample.html b/enyo/samples/WebServiceSample.html new file mode 100644 index 0000000..10dbdc3 --- /dev/null +++ b/enyo/samples/WebServiceSample.html @@ -0,0 +1,21 @@ + + + + WebService Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/enyo/samples/WebServiceSample.js b/enyo/samples/WebServiceSample.js new file mode 100644 index 0000000..78b0f31 --- /dev/null +++ b/enyo/samples/WebServiceSample.js @@ -0,0 +1,32 @@ +enyo.kind({ + name: "enyo.sample.WebServiceSample", + kind: "FittableRows", + classes: "enyo-fit webservice-sample", + components: [ + {kind: "WebService", name:"yql", url: "http://query.yahooapis.com/v1/public/yql?format=json", onResponse:"processResponse", callbackName: "callback"}, + {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ + {content: "YQL: "}, + {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, + {kind: "onyx.PickerDecorator", components: [ + {content:"Choose Scroller", style:"width:100px;"}, + {kind: "onyx.Picker", floating:true, components: [ + {content:"AJAX", active:true}, + {content:"JSON-P"} + ]} + ]}, + {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} + ]}, + {kind: "onyx.TextArea", fit:true, classes:"webservice-sample-source"} + ], + fetch: function() { + // send parameters the remote service using the 'send()' method + this.$.yql.send({ + q: this.$.query.getValue(), + jsonp: (this.$.picker.getSelected().indexInContainer()==2) + }); + }, + processResponse: function(inSender, inEvent) { + // do something with it + this.$.textArea.setValue(JSON.stringify(inEvent.data, null, 2)); + } +}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample1.js b/enyo/samples/assets/Sample1.js new file mode 100644 index 0000000..1b34875 --- /dev/null +++ b/enyo/samples/assets/Sample1.js @@ -0,0 +1,15 @@ +enyo.kind({ + name: "Sample", + kind: "Control", + components: [ + {name: "input", tag: "input"}, + {tag: "br"}, + {name: "button", tag: "button", content: "Set Content", ontap: "buttonTap"}, + {tag: "br"}, + {name: "output", classes: "sample-output"} + ], + buttonTap: function(inSender, inEvent) { + var value = this.$.input.hasNode().value; + this.$.output.setContent(value); + } +}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample2.js b/enyo/samples/assets/Sample2.js new file mode 100644 index 0000000..04fe5ab --- /dev/null +++ b/enyo/samples/assets/Sample2.js @@ -0,0 +1,15 @@ +enyo.kind({ + name: "Sample", + kind: "Control", + components: [ + {name: "input", tag: "input", attributes: {value: "red"}}, + {tag: "br"}, + {tag: "button", content: "Set Color", ontap: "buttonTap"}, + {tag: "br"}, + {name: "output", classes: "sample-output"} + ], + buttonTap: function(inSender, inEvent) { + var color = this.$.input.hasNode().value; + this.$.output.applyStyle("background", color); + } +}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample3.js b/enyo/samples/assets/Sample3.js new file mode 100644 index 0000000..ee0b9ef --- /dev/null +++ b/enyo/samples/assets/Sample3.js @@ -0,0 +1,30 @@ +enyo.kind({ + name: "Sample", + kind: "Control", + components: [ + {name: "input", tag: "input", attributes: {value: "Foo "}}, + {tag: "br"}, + {tag: "button", content: "Add Content", ontap: "addContentTap"}, + {tag: "br"}, + {tag: "button", style: "margin-right: .5em;", content: "Hide", ontap: "hideTap"}, + {tag: "button", style: "margin-right: .5em;", content: "Show", ontap: "showTap"}, + {tag: "button", content: "Toggle class", ontap: "toggleClassTap"}, + {tag: "br"}, + {name: "output", classes: "sample-output"} + ], + addContentTap: function(inSender, inEvent) { + var content = this.$.input.hasNode().value; + this.$.output.addContent(content); + }, + hideTap: function(inSender, inEvent) { + this.$.output.hide(); + }, + showTap: function(inSender, inEvent) { + this.$.output.show(); + }, + toggleClassTap: function(inSender, inEvent) { + var c = "sample-output"; + var has = this.$.output.hasClass(c); + this.$.output.addRemoveClass(c, !has); + } +}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample4.js b/enyo/samples/assets/Sample4.js new file mode 100644 index 0000000..cc2de00 --- /dev/null +++ b/enyo/samples/assets/Sample4.js @@ -0,0 +1,24 @@ +enyo.kind({ + name: "Sample", + kind: "Control", + components: [ + {content: "Create a button control with the given content:", style: "padding: 10px 0;"}, + {name: "input", tag: "input", attributes: {value: "Foo"}, style: "display: block;"}, + {style: "padding: 10px 0;", components: [ + {tag: "button", style: "margin-right: 10px;", content: "Add", ontap: "addTap"}, + {tag: "button", content: "Clear", ontap: "clearTap"}, + ]}, + {name: "output"} + ], + addTap: function(inSender, inEvent) { + var content = this.$.input.hasNode().value; + this.createComponent({ + tag: "button", + content: content, + container: this.$.output + }).render(); + }, + clearTap: function(inSender, inEvent) { + this.$.output.destroyClientControls(); + } +}); \ No newline at end of file diff --git a/enyo/samples/package.js b/enyo/samples/package.js new file mode 100644 index 0000000..e6972c3 --- /dev/null +++ b/enyo/samples/package.js @@ -0,0 +1,19 @@ +enyo.depends( + "$lib/extra/exampler", + "PlatformSample.css", + "PlatformSample.js", + "Playground.css", + "Playground.js", + "AjaxSample.css", + "AjaxSample.js", + "JsonpSample.css", + "JsonpSample.js", + "WebServiceSample.css", + "WebServiceSample.js", + "RepeaterSample.css", + "RepeaterSample.js", + "ScrollerSample.css", + "ScrollerSample.js", + "GestureSample.css", + "GestureSample.js" +); \ No newline at end of file diff --git a/enyo/source/ajax/Ajax.js b/enyo/source/ajax/Ajax.js new file mode 100644 index 0000000..7869f10 --- /dev/null +++ b/enyo/source/ajax/Ajax.js @@ -0,0 +1,255 @@ +/** + _enyo.Ajax_ is a wrapper for _XmlHttpRequest_ that uses + the enyo.Async API. + + _enyo.Ajax_ publishes all the properties of the + enyo.AjaxProperties + object. + + Like _enyo.Async_, _enyo.Ajax_ is an **Object**, not a **Component**. + Do not try to make _enyo.Ajax_ objects inside a _components_ block. + If you want to use _enyo.Ajax_ as a component, you should probably + be using enyo.WebService instead. + + If you make changes to _enyo.Ajax_, be sure to add or update the appropriate + [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). + + For more information, see the documentation on + [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Ajax", + kind: enyo.Async, + //* See enyo.AjaxProperties for the list of properties + //* published by _enyo.Ajax_. + published: enyo.AjaxProperties, + //* @protected + constructor: function(inParams) { + enyo.mixin(this, inParams); + this.inherited(arguments); + }, + //* @public + /** + Sends the Ajax request with parameters _inParams_. _inParams_ values may be + either Strings or Objects. + + _inParams_ as an Object is converted into the url query string. For + instance, passing {q: "searchTerm"} will result in the addition + of the string `q="searchTerm"` to the current url query string. + + _inParams_ as a String is used as the query part of the URL directly. + + _inParams_ will not be converted into a POST body, it will always be used as + part of the URL query string if provided. Use the `postBody` property for + specifying a body. + + When the request is completed, the code will set a `xhrResponse` property + in the `enyo.Ajax` object with the subproperties `status`, `headers`, and + `body`. These cache the results from the XHR for later use. The keys for + the `headers` object have been converted to all lower case as HTTP headers + are case-insensitive. + */ + go: function(inParams) { + this.startTimer(); + this.request(inParams); + return this; + }, + //* @protected + request: function(inParams) { + var parts = this.url.split("?"); + var uri = parts.shift() || ""; + var args = parts.length ? (parts.join("?").split("&")) : []; + // + var query = null; + // + if(enyo.isString(inParams)){ + //If inParams parameter is a string, use it as request body + query = inParams; + } + else{ + //If inParams parameter is not a string, build a query from it + if(inParams){ + query = enyo.Ajax.objectToQuery(inParams); + } + } + // + if (query) { + args.push(query); + query = null; + } + if (this.cacheBust) { + args.push(Math.random()); + } + // + var url = args.length ? [uri, args.join("&")].join("?") : uri; + // + var xhr_headers = {}; + var body; + if (this.method != "GET") { + body = this.postBody; + if (this.method === "POST" && body instanceof enyo.FormData) { + if (body.fake) { + xhr_headers["Content-Type"] = body.getContentType(); + body = body.toString(); + } else { + // Nothing to do as the + // content-type will be + // automagically set according + // to the FormData + } + } else { + xhr_headers["Content-Type"] = this.contentType; + if (body instanceof Object) { + if (this.contentType === "application/json") { + body = JSON.stringify(body); + } else if (this.contentType === "application/x-www-form-urlencoded") { + body = enyo.Ajax.objectToQuery(body); + } + else { + body = body.toString(); + } + } + } + } + enyo.mixin(xhr_headers, this.headers); + // don't pass in headers structure if there are no headers defined as this messes + // up CORS code for IE8-9 + if (enyo.keys(xhr_headers).length === 0) { + xhr_headers = undefined; + } + // + try { + this.xhr = enyo.xhr.request({ + url: url, + method: this.method, + callback: enyo.bind(this, "receive"), + body: body, + headers: xhr_headers, + sync: window.PalmSystem ? false : this.sync, + username: this.username, + password: this.password, + xhrFields: this.xhrFields, + mimeType: this.mimeType + }); + } + catch (e) { + // IE can throw errors here if the XHR would fail CORS checks, + // so catch and turn into a failure. + this.fail(e); + } + }, + receive: function(inText, inXhr) { + if (!this.failed && !this.destroyed) { + var body; + if (typeof inXhr.responseText === "string") { + body = inXhr.responseText; + } else { + // IE carrying a binary + body = inXhr.responseBody; + } + this.xhrResponse = { + status: inXhr.status, + headers: enyo.Ajax.parseResponseHeaders(inXhr), + body: body + }; + if (this.isFailure(inXhr)) { + this.fail(inXhr.status); + } else { + this.respond(this.xhrToResponse(inXhr)); + } + } + }, + fail: function(inError) { + // on failure, explicitly cancel the XHR to prevent + // further responses. cancellation also resets the + // response headers & body, + if (this.xhr) { + enyo.xhr.cancel(this.xhr); + this.xhr = null; + } + this.inherited(arguments); + }, + xhrToResponse: function(inXhr) { + if (inXhr) { + return this[(this.handleAs || "text") + "Handler"](inXhr); + } + }, + isFailure: function(inXhr) { + // if any exceptions are thrown while checking fields in the xhr, + // assume a failure. + try { + var text = ""; + // work around IE8-9 bug where accessing responseText will thrown error + // for binary requests. + if (typeof inXhr.responseText === "string") { + text = inXhr.responseText; + } + // Follow same failure policy as jQuery's Ajax code + // CORS failures on FireFox will have status 0 and no responseText, + // so treat that as failure. + if (inXhr.status === 0 && text === "") { + return true; + } + // Otherwise, status 0 may be good for local file access. We treat the range + // 1-199 and 300+ as failure (only 200-series code are OK). + return (inXhr.status !== 0) && (inXhr.status < 200 || inXhr.status >= 300); + } + catch (e) { + return true; + } + }, + xmlHandler: function(inXhr) { + return inXhr.responseXML; + }, + textHandler: function(inXhr) { + return inXhr.responseText; + }, + jsonHandler: function(inXhr) { + var r = inXhr.responseText; + try { + return r && enyo.json.parse(r); + } catch (x) { + enyo.warn("Ajax request set to handleAs JSON but data was not in JSON format"); + return r; + } + }, + statics: { + objectToQuery: function(/*Object*/ map) { + var enc = encodeURIComponent; + var pairs = []; + var backstop = {}; + for (var name in map){ + var value = map[name]; + if (value != backstop[name]) { + var assign = enc(name) + "="; + if (enyo.isArray(value)) { + for (var i=0; i < value.length; i++) { + pairs.push(assign + enc(value[i])); + } + } else { + pairs.push(assign + enc(value)); + } + } + } + return pairs.join("&"); + }, + parseResponseHeaders: function(xhr) { + var headers = {}; + var headersStr = []; + if (xhr.getAllResponseHeaders) { + headersStr = xhr.getAllResponseHeaders().split(/\r?\n/); + } + for (var i = 0; i < headersStr.length; i++) { + var headerStr = headersStr[i]; + var index = headerStr.indexOf(': '); + if (index > 0) { + var key = headerStr.substring(0, index).toLowerCase(); + var val = headerStr.substring(index + 2); + headers[key] = val; + } + } + return headers; + } + } +}); diff --git a/enyo/source/ajax/AjaxProperties.js b/enyo/source/ajax/AjaxProperties.js new file mode 100644 index 0000000..bcd7405 --- /dev/null +++ b/enyo/source/ajax/AjaxProperties.js @@ -0,0 +1,68 @@ +/** + Common set of published properties used in both + enyo.Ajax and + enyo.WebService. +*/ +enyo.AjaxProperties = { + /** + When true, appends a random number as a parameter for GET requests + to try to force a new fetch of the resource instead of reusing a local cache. + */ + cacheBust: true, + /** + The URL for the service. This can be a relative URL if used to fetch resources bundled with the application. + */ + url: "", + /** + The HTTP method to use for the request, defaults to GET. Supported values include + "GET", "POST", "PUT", and "DELETE". + */ + method: "GET", // {value: "GET", options: ["GET", "POST", "PUT", "DELETE"]}, + /** + How the response will be handled. + Supported values are: "json", "text", "xml" + */ + handleAs: "json", // {value: "json", options: ["text", "json", "xml"]}, + /** + The Content-Type header for the request as a String. + */ + contentType: "application/x-www-form-urlencoded", + /** + If true, makes a synchronous (blocking) call, if supported. Synchronous requests + are not supported on HP webOS. + */ + sync: false, + /** + Optional additional request headers as a JS object, e.g. + { "X-My-Header": "My Value", "Mood": "Happy" } or null. + */ + headers: null, + /** + The content for the request body for POST/PUT methods. + + When postBody is a Buffer or a String, it is passed verbatim in the request body. + When postBody is an Object, the way it is encoded depends on the contentType: + + * application/json => JSON.stringify + * application/x-www-urlencoed => url-encoded parameters + * multipart/form-data => passed as fields in enyo.FormData (XHR2 emulation) + */ + postBody: "", + /** + The optional user name to use for authentication purposes. + */ + username: "", + /** + The optional password to use for authentication purposes. + */ + password: "", + /** + Optional object with fields to pass directly to the underlying XHR object. + One example is the _withCredentials_ flag used for cross-origin requests. + */ + xhrFields: null, + /** + Optional string to override the MIME-Type header. + */ + mimeType: null +}; diff --git a/enyo/source/ajax/Async.js b/enyo/source/ajax/Async.js new file mode 100644 index 0000000..6a2fb9f --- /dev/null +++ b/enyo/source/ajax/Async.js @@ -0,0 +1,128 @@ +/** + _enyo.Async_ is the base kind for handling asynchronous operations. + + _enyo.Async_ is an **Object**, not a **Component**; thus, you may not declare + an _Async_ in a _components_ block. If you want to use _Async_ as a + component, you should probably be using + enyo.WebService instead. + + An Async object represents a task that has not yet completed. You may attach + callback functions to an Async, to be called when the task completes or + encounters an error. + + More information on _Async_ and its usage is available in the documentation on + Consuming Web Services + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Async", + kind: enyo.Object, + published: { + /** + If set to a non-zero value, the number of milliseconds to + wait after the _go_ call before failing with the "timeout" error + */ + timeout: 0 + }, + //* @protected + failed: false, + context: null, + constructor: function() { + this.responders = []; + this.errorHandlers = []; + }, + accumulate: function(inArray, inMethodArgs) { + var fn = (inMethodArgs.length < 2) ? inMethodArgs[0] : enyo.bind(inMethodArgs[0], inMethodArgs[1]); + inArray.push(fn); + }, + //* @public + /** + Registers a response function. + First parameter is an optional _this_ context for the response method. + Second (or only) parameter is the function object. + */ + response: function(/* [inContext], inResponder */) { + this.accumulate(this.responders, arguments); + return this; + }, + /** + Registers an error handler. + First parameter is an optional _this_ context for the response method. + Second (or only) parameter is the function object. + */ + error: function(/* [inContext], inResponder */) { + this.accumulate(this.errorHandlers, arguments); + return this; + }, + //* @protected + route: function(inAsync, inValue) { + var r = enyo.bind(this, "respond"); + inAsync.response(function(inSender, inValue) { + r(inValue); + }); + var f = enyo.bind(this, "fail"); + inAsync.error(function(inSender, inValue) { + f(inValue); + }); + inAsync.go(inValue); + }, + handle: function(inValue, inHandlers) { + var r = inHandlers.shift(); + if (r) { + if (r instanceof enyo.Async) { + this.route(r, inValue); + } else { + // handler can return a new 'value' + var v = enyo.call(this.context || this, r, [this, inValue]); + // ... but only if it returns something other than undefined + v = (v !== undefined) ? v : inValue; + // next handler + (this.failed ? this.fail : this.respond).call(this, v); + } + } + }, + startTimer: function() { + this.startTime = enyo.now(); + if (this.timeout) { + this.timeoutJob = setTimeout(enyo.bind(this, "timeoutComplete"), this.timeout); + } + }, + endTimer: function() { + if (this.timeoutJob) { + this.endTime = enyo.now(); + clearTimeout(this.timeoutJob); + this.timeoutJob = null; + this.latency = this.endTime - this.startTime; + } + }, + timeoutComplete: function() { + this.timedout = true; + this.fail("timeout"); + }, + //* @protected + //* Called as part of the async implementation; triggers the handler chain. + respond: function(inValue) { + this.failed = false; + this.endTimer(); + this.handle(inValue, this.responders); + }, + //* @public + //* Can be called from any handler to trigger the error chain. + fail: function(inError) { + this.failed = true; + this.endTimer(); + this.handle(inError, this.errorHandlers); + }, + //* Called from an error handler; clears the error condition and resumes + //* calling handler methods. + recover: function() { + this.failed = false; + }, + //* Starts the async activity. Overridden in subkinds. + go: function(inValue) { + enyo.asyncMethod(this, function() { + this.respond(inValue); + }); + return this; + } +}); diff --git a/enyo/source/ajax/Jsonp.js b/enyo/source/ajax/Jsonp.js new file mode 100644 index 0000000..2e6463a --- /dev/null +++ b/enyo/source/ajax/Jsonp.js @@ -0,0 +1,123 @@ +/** + _enyo.JsonpRequest_ is a specialized form of + enyo.Async used for making JSONP requests to a + remote server. This differs from the normal XmlHTTPRequest call in that the + external resource is loaded using a <script> tag. This allows us to + bypass the same-domain rules that normally apply to XHR, since the browser + will load scripts from any address. + + If you make changes to _enyo.JsonpRequest_, be sure to add or update the + appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). + + For more information, see the documentation on + [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.JsonpRequest", + kind: enyo.Async, + published: { + //* The URL for the service + url: "", + //* Optional character set to use to interpret the return data + charset: null, + /** + Name of the argument that holds the callback name. For example, the + Twitter search API uses "callback" as the parameter to hold the + name of the called function. We will automatically add this to + the encoded arguments. + */ + callbackName: "callback", + /** + When true, appends a random number as a parameter for GET requests + to try to force a new fetch of the resource instead of reusing a + local cache + */ + cacheBust: true + }, + statics: { + // Counter to allow creation of unique name for each JSONP request + nextCallbackID: 0 + }, + //* @protected + addScriptElement: function() { + var script = document.createElement('script'); + script.src = this.src; + script.async = "async"; + if (this.charset) { + script.charset = this.charset; + } + // most modern browsers also have an onerror handler + script.onerror = enyo.bind(this, function() { + // we don't get an error code, so we'll just use the generic 400 error status + this.fail(400); + }); + // add script before existing script to make sure it's in a valid part of document + // http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ + var first = document.getElementsByTagName('script')[0]; + first.parentNode.insertBefore(script, first); + this.scriptTag = script; + }, + removeScriptElement: function() { + var script = this.scriptTag; + this.scriptTag = null; + script.onerror = null; + if (script.parentNode) { + script.parentNode.removeChild(script); + } + }, + constructor: function(inParams) { + enyo.mixin(this, inParams); + this.inherited(arguments); + }, + //* @public + //* Starts the JSONP request. + go: function(inParams) { + this.startTimer(); + this.jsonp(inParams); + return this; + }, + //* @protected + jsonp: function(inParams) { + var callbackFunctionName = "enyo_jsonp_callback_" + (enyo.JsonpRequest.nextCallbackID++); + // + this.src = this.buildUrl(inParams, callbackFunctionName); + this.addScriptElement(); + // + window[callbackFunctionName] = enyo.bind(this, this.respond); + // + // setup cleanup handlers for JSONP completion and failure + var cleanup = enyo.bind(this, function() { + this.removeScriptElement(); + window[callbackFunctionName] = null; + }); + this.response(cleanup); + this.error(cleanup); + }, + buildUrl: function(inParams, inCallbackFunctionName) { + var parts = this.url.split("?"); + var uri = parts.shift() || ""; + var args = parts.join("?").split("&"); + // + var bodyArgs = this.bodyArgsFromParams(inParams, inCallbackFunctionName); + args.push(bodyArgs); + if (this.cacheBust) { + args.push(Math.random()); + } + // + return [uri, args.join("&")].join("?"); + }, + // for a string version of inParams, we follow the convention of + // replacing the string "=?" with the callback name. For the more + // common case of inParams being an object, we'll add a argument named + // using the callbackName published property. + bodyArgsFromParams: function(inParams, inCallbackFunctionName) { + if (enyo.isString(inParams)) { + return inParams.replace("=?", "=" + inCallbackFunctionName); + } else { + var params = enyo.mixin({}, inParams); + params[this.callbackName] = inCallbackFunctionName; + return enyo.Ajax.objectToQuery(params); + } + } +}); \ No newline at end of file diff --git a/enyo/source/ajax/WebService.js b/enyo/source/ajax/WebService.js new file mode 100644 index 0000000..337b254 --- /dev/null +++ b/enyo/source/ajax/WebService.js @@ -0,0 +1,114 @@ +//* @protected +enyo.kind({ + name: "enyo._AjaxComponent", + kind: enyo.Component, + published: enyo.AjaxProperties +}); + +//* @public +/** + _enyo.WebService_ is a component that performs Web requests (_XmlHttpRequest_). + + Internally, _enyo.WebService_ uses _enyo.Async_ subkinds (namely, + enyo.Ajax and + enyo.JsonpRequest) to manage transactions. + The _send_ method returns the Async instance used by the request. + + _enyo.WebService_ uses _enyo.Ajax_ by default and, like _enyo.Ajax_, it + publishes all the properties of the + enyo.AjaxProperties object. + + To use `enyo.JsonpRequest` instead of `enyo.Ajax`, set `json` to `true`. + + If you make changes to _enyo.WebService_, be sure to add or update the + appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). + + For more information, see the documentation on + [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.WebService", + kind: enyo._AjaxComponent, + published: { + //* Set to true to use JSONP protocol + jsonp: false, + /** + When using JSONP, the name of the callback parameter. + Note that this not the name of a callback function, but only + the name of the callback parameter. Enyo will create an + internal callback function as necessary. + */ + callbackName: "callback", + /** + When using JSONP, optional character set to use to interpret the + return data + */ + charset: null, + /** + If set to a non-zero value, the number of milliseconds to + wait after the _send_ call before failing with a "timeout" error + */ + timeout: 0 + }, + events: { + /** + Fires when a response is received. + + _inEvent.ajax_ contains the Async instance associated with the request. + + _inEvent.data_ contains the response data. + */ + onResponse: "", + /** + Fires when an error is received. + + _inEvent.ajax_ contains the Async instance associated with the request. + + _inEvent.data_ contains the error data. + */ + onError: "" + }, + //* @protected + constructor: function(inProps) { + this.inherited(arguments); + }, + //* @public + /** + Sends a Web request with the passed-in parameters, returning the + associated Async instance. + + _inProps_ is an optional object parameterthat can be used to override some + of the AJAX properties for this request, such as setting a _postBody_. + */ + send: function(inParams, inProps) { + return this.jsonp ? this.sendJsonp(inParams, inProps) : this.sendAjax(inParams, inProps); + }, + //* @protected + sendJsonp: function(inParams, inProps) { + var jsonp = new enyo.JsonpRequest(); + for (var n in {'url':1, 'callbackName':1, 'charset':1, 'timeout':1}) { + jsonp[n] = this[n]; + } + enyo.mixin(jsonp, inProps); + return this.sendAsync(jsonp, inParams); + }, + sendAjax: function(inParams, inProps) { + var ajax = new enyo.Ajax(inProps); + for (var n in enyo.AjaxProperties) { + ajax[n] = this[n]; + } + ajax.timeout = this.timeout; + enyo.mixin(ajax, inProps); + return this.sendAsync(ajax, inParams); + }, + sendAsync: function(inAjax, inParams) { + return inAjax.go(inParams).response(this, "response").error(this, "error"); + }, + response: function(inSender, inData) { + this.doResponse({ajax: inSender, data: inData}); + }, + error: function(inSender, inData) { + this.doError({ajax: inSender, data: inData}); + } +}); diff --git a/enyo/source/ajax/cookie.js b/enyo/source/ajax/cookie.js new file mode 100644 index 0000000..c76e1aa --- /dev/null +++ b/enyo/source/ajax/cookie.js @@ -0,0 +1,50 @@ +//* @public + +/** + Gets a named value from the document cookie. +*/ +enyo.getCookie = function(inName) { + var matches = document.cookie.match(new RegExp("(?:^|; )" + inName + "=([^;]*)")); + return matches ? decodeURIComponent(matches[1]) : undefined; +}; + +/** + Sets a named value in the document cookie, with properties. + + Properties in the optional _inProps_ argument are attached to the cookie. + _inProps_ may have an _expires_ property, which can be a number of days, a + Date object, or a UTC time string. + + To remove a cookie, use an _inProps_ value of { "Max-Age": 0 }. + + If developing in the Google Chrome browser with a local file as your + application, start Chrome with the --enable-file-cookies switch + to allow cookies to be set. +*/ +enyo.setCookie = function(inName, inValue, inProps) { + var cookie = inName + "=" + encodeURIComponent(inValue); + var p = inProps || {}; + // + // FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs? + var exp = p.expires; + if (typeof exp == "number") { + var d = new Date(); + d.setTime(d.getTime() + exp*24*60*60*1000); + exp = d; + } + if (exp && exp.toUTCString) { + p.expires = exp.toUTCString(); + } + // + var name, value; + for (name in p){ + cookie += "; " + name; + value = p[name]; + if (value !== true) { + cookie += "=" + value; + } + } + // + //enyo.log(cookie); + document.cookie = cookie; +}; diff --git a/enyo/source/ajax/formdata.js b/enyo/source/ajax/formdata.js new file mode 100644 index 0000000..1d47188 --- /dev/null +++ b/enyo/source/ajax/formdata.js @@ -0,0 +1,91 @@ +/** + +_enyo.FormData_ is an [XHR2](http://www.w3.org/TR/XMLHttpRequest/) +`FormData` implementation. It is used to send `multipart/form-data` +Ajax requests. _enyo.Blob_ is the associated content provider for +file-parts. + +Note that in IE<10, both _enyo.FormData_ and _enyo.Blob_ are limited +to `String` content--an _enyo.Blob_ may only be instantiated using an +`Array` or `String`. + +_enyo.FormData_ is inspired by +[html5-formdata](https://github.com/francois2metz/html5-formdata/blob/master/formdata.js). + + Emulate FormData for some browsers + MIT License + (c) 2010 Francois de Metz + + */ +(function(w) { + if (w.FormData) { + try { + var t1 = new w.FormData(); + var t2 = new w.Blob(); + // Android Chrome 18 will throw an error trying to create these + enyo.FormData = w.FormData; + enyo.Blob = w.Blob; + return; + } + catch (e) { + // ignore error and fall through to fake FormData code + } + } + function FormData() { + this.fake = true; + this._fields = []; + // This generates a 50 character boundary similar to + // those used by Firefox. They are optimized for + // boyer-moore parsing. + this.boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + this.boundary += Math.floor(Math.random() * 10).toString(16); + } + } + FormData.prototype.getContentType = function() { + return "multipart/form-data; boundary=" + this.boundary; + }; + FormData.prototype.append = function(key, value, filename) { + this._fields.push([key, value, filename]); + }; + FormData.prototype.toString = function() { + var boundary = this.boundary; + var body = ""; + enyo.forEach(this._fields, function(field) { + body += "--" + boundary + "\r\n"; + if (field[2] || field[1].name) { + // file upload + var file = field[1], filename = field[2] || file.name; + body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ filename +"\"\r\n"; + body += "Content-Type: "+ file.type +"\r\n\r\n"; + body += file.getAsBinary() + "\r\n"; + } else { + // key-value field + body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n"; + body += field[1] + "\r\n"; + } + }); + body += "--" + boundary +"--"; + return body; + }; + enyo.FormData = FormData; + + function Blob(inBufs, inOpts) { + this.name = inOpts.name; + this.type = inOpts.type || 'application/octet-stream'; + if (!enyo.isArray(inBufs)) { + throw new Error('enyo.Blob only handles Arrays of Strings'); + } + if ((inBufs.length > 0) && typeof inBufs[0] !== 'string') { + throw new Error('enyo.Blob only handles Arrays of Strings'); + } + this._bufs = inBufs; // leave byte arrays un-touched + } + Blob.prototype.getAsBinary = function() { + var empty = '', + content = empty.concat.apply(empty, this._bufs); + return content; + }; + enyo.Blob = Blob; + +})(window); diff --git a/enyo/source/ajax/json.js b/enyo/source/ajax/json.js new file mode 100644 index 0000000..d9b7bb7 --- /dev/null +++ b/enyo/source/ajax/json.js @@ -0,0 +1,21 @@ +enyo.json = { + //* @public + /** + Returns a JSON string for a given object, using native stringify + routine. + inValue is the Object to be converted to JSON. + inReplacer is the optional value inclusion array or replacement function. + inSpace is the optional number or string to use for pretty-printing whitespace. + */ + stringify: function(inValue, inReplacer, inSpace) { + return JSON.stringify(inValue, inReplacer, inSpace); + }, + /** + Returns a JavaScript object for a given JSON string, using native stringify + routine. + inJson is the JSON string to be converted to a JavaScript object. + */ + parse: function(inJson, inReviver) { + return inJson ? JSON.parse(inJson, inReviver) : null; + } +}; diff --git a/enyo/source/ajax/package.js b/enyo/source/ajax/package.js new file mode 100644 index 0000000..41fca45 --- /dev/null +++ b/enyo/source/ajax/package.js @@ -0,0 +1,11 @@ +enyo.depends( + "Async.js", + "json.js", + "cookie.js", + "xhr.js", + "formdata.js", + "AjaxProperties.js", + "Ajax.js", + "Jsonp.js", + "WebService.js" +); \ No newline at end of file diff --git a/enyo/source/ajax/xhr.js b/enyo/source/ajax/xhr.js new file mode 100644 index 0000000..cdd7fc0 --- /dev/null +++ b/enyo/source/ajax/xhr.js @@ -0,0 +1,143 @@ +//* @protected +/** + If you make changes to _enyo.xhr_, be sure to add or update the appropriate + [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). +*/ +enyo.xhr = { + /** + inParams is an Object that may contain these properties: + + - _url_: The URL to request (required). + - _method_: The HTTP method to use for the request. Defaults to GET. + - _callback_: Called when request is completed. (Optional) + - _body_: Specific contents for the request body for POST method. (Optional) + - _headers_: Additional request headers. (Optional). Given headers override the ones that Enyo may set by default (`null` explictly removing the header from the AJAX request). + - _username_: The optional user name to use for authentication purposes. + - _password_: The optional password to use for authentication purposes. + - _xhrFields_: Optional object containing name/value pairs to mix directly into the generated xhr object. + - _mimeType_: Optional string to override the MIME-Type. + */ + request: function(inParams) { + var xhr = this.getXMLHttpRequest(inParams); + var url = enyo.path.rewrite(this.simplifyFileURL(inParams.url)); + // + var method = inParams.method || "GET"; + var async = !inParams.sync; + // + if (inParams.username) { + xhr.open(method, url, async, inParams.username, inParams.password); + } else { + xhr.open(method, url, async); + } + // + enyo.mixin(xhr, inParams.xhrFields); + // only setup handler when we have a callback + if (inParams.callback) { + this.makeReadyStateHandler(xhr, inParams.callback); + } + // + inParams.headers = inParams.headers || {}; + // work around iOS 6 bug where non-GET requests are cached + // see http://www.einternals.com/blog/web-development/ios6-0-caching-ajax-post-requests + // not sure (yet) wether this will be required for later ios releases + if (method !== "GET" && enyo.platform.ios && enyo.platform.ios >= 6) { + if (inParams.headers["cache-control"] !== null) { + inParams.headers["cache-control"] = inParams.headers['cache-control'] || "no-cache"; + } + } + // user-set headers override any platform-default + if (xhr.setRequestHeader) { + for (var key in inParams.headers) { + if (inParams.headers[key]) { + xhr.setRequestHeader(key, inParams.headers[key]); + } + } + } + // + if((typeof xhr.overrideMimeType == "function") && inParams.mimeType) { + xhr.overrideMimeType(inParams.mimeType); + } + // + xhr.send(inParams.body || null); + if (!async && inParams.callback) { + xhr.onreadystatechange(xhr); + } + return xhr; + }, + //* remove any callbacks that might be set from Enyo code for an existing XHR + //* and stop the XHR from completing. + cancel: function(inXhr) { + if (inXhr.onload) { + inXhr.onload = null; + } + if (inXhr.onreadystatechange) { + inXhr.onreadystatechange = null; + } + if (inXhr.abort) { + inXhr.abort(); + } + }, + //* @protected + makeReadyStateHandler: function(inXhr, inCallback) { + if (window.XDomainRequest && inXhr instanceof XDomainRequest) { + inXhr.onload = function() { + var text; + if (typeof inXhr.responseText === "string") { + text = inXhr.responseText; + } + inCallback.apply(null, [text, inXhr]); + }; + } + inXhr.onreadystatechange = function() { + if (inXhr.readyState == 4) { + var text; + if (typeof inXhr.responseText === "string") { + text = inXhr.responseText; + } + inCallback.apply(null, [text, inXhr]); + } + }; + }, + inOrigin: function(inUrl) { + var a = document.createElement("a"), result = false; + a.href = inUrl; + // protocol is ":" for relative URLs + if (a.protocol === ":" || + (a.protocol === window.location.protocol && + a.hostname === window.location.hostname && + a.port === (window.location.port || + (window.location.protocol === "https:" ? "443" : "80")))) { + result = true; + } + return result; + }, + simplifyFileURL: function(inUrl) { + var a = document.createElement("a"), result = false; + a.href = inUrl; + // protocol is ":" for relative URLs + if (a.protocol === "file:" || + a.protocol === ":" && window.location.protocol === "file:") { + // leave off search and hash parts of the URL + return a.protocol + '//' + a.host + a.pathname; + } else if (a.protocol === ":" && window.location.protocol === "x-wmapp0:") { + // explicitly return absolute URL for Windows Phone 8, as an absolute path is required for local files + return window.location.protocol + "//" + window.location.pathname.split('/')[0] + "/" + a.host + a.pathname; + } else { + return inUrl; + } + }, + getXMLHttpRequest: function(inParams) { + try { + // only use XDomainRequest when it exists, no extra headers were set, and the + // target URL maps to a domain other than the document origin. + if (enyo.platform.ie < 10 && window.XDomainRequest && !inParams.headers && + !this.inOrigin(inParams.url) && !/^file:\/\//.test(window.location.href)) { + return new XDomainRequest(); + } + } catch(e) {} + try { + return new XMLHttpRequest(); + } catch(e) {} + return null; + } +}; diff --git a/enyo/source/boot/boot.js b/enyo/source/boot/boot.js new file mode 100644 index 0000000..18a67f7 --- /dev/null +++ b/enyo/source/boot/boot.js @@ -0,0 +1,133 @@ +// Used when a certain platform restricts functionality due to security +enyo.execUnsafeLocalFunction = function(e) { + // Querying {MSApp} object - Windows 8 + if (typeof MSApp === "undefined") { + e(); + } + else { + MSApp.execUnsafeLocalFunction(e); + } +}; + +// machine for a loader instance +enyo.machine = { + sheet: function(inPath) { + var type = "text/css"; + var rel = "stylesheet"; + var isLess = (inPath.slice(-5) == ".less"); + if (isLess) { + if (window.less) { + // If client-side less is loaded, insert the less stylesheet + type = "text/less"; + rel = "stylesheet/less"; + } else { + // Otherwise, we expect a css file of the same name to exist + inPath = inPath.slice(0, inPath.length-4) + "css"; + } + } + var link; + if (enyo.runtimeLoading || isLess) { + link = document.createElement('link'); + link.href = inPath; + link.media = "screen"; + link.rel = rel; + link.type = type; + document.getElementsByTagName('head')[0].appendChild(link); + } else { + link = function() { + document.write(''); + }; + enyo.execUnsafeLocalFunction(link); + } + if (isLess && window.less) { + less.sheets.push(link); + if (!enyo.loader.finishCallbacks.lessRefresh) { + enyo.loader.finishCallbacks.lessRefresh = function() { + less.refresh(true); + }; + } + } + }, + script: function(inSrc, onLoad, onError) { + if (!enyo.runtimeLoading) { + document.write(''); + } else { + var script = document.createElement('script'); + script.src = inSrc; + script.onload = onLoad; + script.onerror = onError; + document.getElementsByTagName('head')[0].appendChild(script); + } + }, + inject: function(inCode) { + document.write('' + inCode + ""); + } +}; + +// create a dependency processor using our script machine +enyo.loader = new enyo.loaderFactory(enyo.machine); + +// dependency API uses enyo loader +enyo.depends = function() { + var ldr = enyo.loader; + if (!ldr.packageFolder) { + var tag = enyo.locateScript("package.js"); + if (tag && tag.path) { + ldr.aliasPackage(tag.path); + ldr.packageFolder = tag.path + "/"; + //console.log("detected PACKAGEFOLDER [" + ldr.packageFolder + "]"); + } + } + ldr.load.apply(ldr, arguments); +}; + +// Runtime loader +// Usage: enyo.load(depends, [onLoadCallback]) +// where - depends is string or array of string paths to package.js, script, or css to load +// - doneCallback is fired after file or package loading has completed +// Only one file/package is loaded at a time; additional calls are queued and loading deferred +(function() { + var enyo = window.enyo; + var runtimeLoadQueue = []; + enyo.load = function(depends, onLoadCallback) { + runtimeLoadQueue.push(arguments); + if (!enyo.runtimeLoading) { + enyo.runtimeLoading = true; + runtimeLoad(); + } + }; + function runtimeLoad(onLoad) { + if (onLoad) { + onLoad(); // Run user callback function + } + if (runtimeLoadQueue.length) { + var args = runtimeLoadQueue.shift(); + var depends = args[0]; + var dependsArg = enyo.isArray(depends) ? depends : [depends]; + var onLoadCallback = args[1]; + enyo.loader.finishCallbacks.runtimeLoader = function() { + // Once loader is done loading a package, we chain a call to runtimeLoad(), + // which will call the onLoadCallback from the original load call, passing + // a reference to the depends argument from the original call for tracking, + // followed by kicking off any additionally queued load() calls + runtimeLoad(function() { + if (onLoadCallback) { + onLoadCallback(depends); + } + }); + }; + enyo.loader.packageFolder = "./"; + // Kick off next queued call to loader + enyo.depends.apply(this, dependsArg); + } else { + enyo.runtimeLoading = false; + enyo.loader.packageFolder = ""; + } + } +})(); + +// predefined path aliases +enyo.path.addPaths({ + enyo: enyo.args.root, + lib: "$enyo/../lib" +}); \ No newline at end of file diff --git a/enyo/source/boot/enyo.js b/enyo/source/boot/enyo.js new file mode 100644 index 0000000..a1126d5 --- /dev/null +++ b/enyo/source/boot/enyo.js @@ -0,0 +1,31 @@ +(function() { + // enyo can use information from the script tag that loads this bootstrap file + var thisScript = "enyo.js"; + + enyo = window.enyo || {}; + + enyo.locateScript = function(inName) { + var scripts = document.getElementsByTagName("script"); + for (var i=scripts.length-1, s, src, l=inName.length; (i>=0) && (s=scripts[i]); i--) { + if (!s.located) { + src = s.getAttribute("src") || ""; + if (src.slice(-l) == inName) { + s.located = true; + return {path: src.slice(0, Math.max(0, src.lastIndexOf("/"))), node: s}; + } + } + } + }; + + enyo.args = enyo.args || {}; + + var tag = enyo.locateScript(thisScript); + if (tag) { + // infer the framework path from the document, unless the user has specified one explicitly + enyo.args.root = (enyo.args.root || tag.path).replace("/source", ""); + // all attributes of the bootstrap script tag become enyo.args + for (var i=0, al = tag.node.attributes.length, it; (i < al) && (it = tag.node.attributes.item(i)); i++) { + enyo.args[it.nodeName] = it.value; + } + } +})(); \ No newline at end of file diff --git a/enyo/source/boot/package.js b/enyo/source/boot/package.js new file mode 100644 index 0000000..adc2873 --- /dev/null +++ b/enyo/source/boot/package.js @@ -0,0 +1,5 @@ +enyo.depends( + "enyo.js", + "../../loader.js", + "boot.js" +); \ No newline at end of file diff --git a/enyo/source/dom/Control.js b/enyo/source/dom/Control.js new file mode 100644 index 0000000..1ea3bea --- /dev/null +++ b/enyo/source/dom/Control.js @@ -0,0 +1,879 @@ +/** + _enyo.Control_ is a component that controls a DOM node (i.e., an element in + the user interface). Controls are generally visible and the user often + interacts with them directly. While things like buttons and input boxes are + obviously controls, in Enyo, a control may become as complex as an entire + application. + + If you make changes to _enyo.Control_, be sure to add or update the appropriate + [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). + + For more information, see the documentation on + Controls + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Control", + kind: enyo.UiComponent, + published: { + /** + HTML tag name to use for the control. If null, no tag is generated; + only the contents are used. + */ + tag: "div", + //* Hash of DOM attributes to apply to the generated HTML tag + attributes: null, + //* Space-delimited set of CSS classes to apply to the generated HTML tag + classes: "", + //* Style attribute to apply to the generated HTML tag + style: "", + /** + Content that will be generated inside the HTML tag; defaults to + plain text unless _allowHtml_ is true + */ + content: "", + //* Boolean indicating whether the tag will be visible in the document + showing: true, + //* If false, HTML codes in _content_ are escaped before rendering + allowHtml: false, + // + // convenience properties for common attributes + // + //* Shortcut for setting _src_ attribute in _attributes_ hash. Overrides that value. + src: "", + // + // esoteric + // + /** + Set to false if the control should not generate any HTML. Used to + inhibit generation of popups until they're shown at runtime. + */ + canGenerate: true, + // + // ad hoc properties: + // + /** + Flag used by control layouts to determine which control will expand + to fill the available space. This only has meaning when the control + is being used as a child of a control with a version of FittableLayout + as its layoutKind. + */ + fit: false, + //* Used by Ares design editor for design objects + isContainer: false + }, + handlers: { + //* Controls will call a user-provided _tap_ method when tapped upon. + ontap: "tap" + }, + //* The default kind for controls created inside this control that don't + //* specify their own kind + defaultKind: "Control", + //* A set of CSS classes that are applied to controls created inside this control + controlClasses: "", + //* @protected + node: null, + generated: false, + create: function() { + // initialize style databases + this.initStyles(); + // superkind initialization + this.inherited(arguments); + // 'showing' is tertiary method for modifying display style + // setting 'display: none;' style at initialization time will + // not work if 'showing' is true. + this.showingChanged(); + // Notes: + // - 'classes' does not reflect the complete set of classes on an object; the complete set is in + // this.attributes.class. The '*Class' apis affect this.attributes.class. + // - use addClass instead of setClasses here, by convention 'classes' is reserved for instance objects + // - inheritors should 'addClass' to add classes + // - setClasses removes the old classes and adds the new one, setClassAttribute replaces all classes + this.addClass(this.kindClasses); + this.addClass(this.classes); + this.initProps(["id", "content", "src"]); + }, + destroy: function() { + this.removeNodeFromDom(); + enyo.Control.unregisterDomEvents(this.id); + this.inherited(arguments); + }, + importProps: function(inProps) { + this.inherited(arguments); + // each instance has its own attributes array, the union of the prototype attributes and user-specified attributes + this.attributes = enyo.mixin(enyo.clone(this.kindAttributes), this.attributes); + }, + initProps: function(inPropNames) { + // for each named property, trigger the *Changed handler if the property value is truthy + for (var i=0, n, cf; (n=inPropNames[i]); i++) { + if (this[n]) { + // FIXME: awkward + cf = n + "Changed"; + if (this[cf]) { + this[cf](); + } + } + } + }, + classesChanged: function(inOld) { + this.removeClass(inOld); + this.addClass(this.classes); + }, + // modify components we create ourselves + /* + adjustComponentProps: function(inProps) { + if (this.controlClasses) { + inProps.classes = (inProps.classes ? inProps.classes + " " : "") + this.controlClasses; + } + this.inherited(arguments); + }, + */ + addChild: function(inControl) { + inControl.addClass(this.controlClasses); + this.inherited(arguments); + }, + removeChild: function(inControl) { + this.inherited(arguments); + inControl.removeClass(this.controlClasses); + }, + // event filter + strictlyInternalEvents: {onenter: 1, onleave: 1}, + dispatchEvent: function(inEventName, inEvent, inSender) { + // prevent dispatch and bubble of events that are strictly internal (e.g. enter/leave) + if (this.strictlyInternalEvents[inEventName] && this.isInternalEvent(inEvent)) { + return true; + } + return this.inherited(arguments); + }, + isInternalEvent: function(inEvent) { + var rdt = enyo.dispatcher.findDispatchTarget(inEvent.relatedTarget); + return rdt && rdt.isDescendantOf(this); + }, + // + //* @public + /** + Returns the DOM node representing the control. + If the control is not currently rendered, returns null. + + If hasNode() returns a value, the _node_ property will be valid and + can be checked directly. + + Once hasNode() is called, the returned value is made available in + the _node_ property of this control. + + A control will only return a node if it has been rendered. + + if (this.hasNode()) { + enyo.log(this.node.nodeType); + } + */ + hasNode: function() { + // 'generated' is used to gate access to expensive findNodeById call + return this.generated && (this.node || this.findNodeById()); + }, + /** + Appends the string value of _inAddendum_ to the _content_ of this + control. + */ + addContent: function(inAddendum) { + this.setContent(this.content + inAddendum); + }, + /** + Gets the value of an attribute on this object. + + If this control has a node, the attribute value is retrieved from the + node; otherwise, it's read from the _attributes_ property of the control + itself. + + Caveat: If the control is rendered, the _attributes_ property is used to + construct the rendering, and values that have changed on the node itself + are lost. + + // Get the value attribute for this DomNode + var value = this.getAttribute("tabIndex"); + */ + getAttribute: function(inName) { + return this.hasNode() ? this.node.getAttribute(inName) : this.attributes[inName]; + }, + /** + Sets the value of an attribute on this object. Pass null _inValue_ to + remove an attribute. + + // set the tabIndex attribute for this DomNode + this.setAttribute("tabIndex", 3); + ... + // remove the index attribute + this.setAttribute("index", null); + */ + setAttribute: function(inName, inValue) { + this.attributes[inName] = inValue; + if (this.hasNode()) { + this.attributeToNode(inName, inValue); + } + this.invalidateTags(); + }, + /** + Gets the value of a property named _inName_ directly from the DOM node. + A caller-specified default value, _inDefault_, is returned when the DOM + node has not yet been created. + */ + getNodeProperty: function(inName, inDefault) { + if (this.hasNode()) { + return this.node[inName]; + } else { + return inDefault; + } + }, + /** + Sets the value of the _inName_ property on the control's DOM node to + _inValue_, if and only if the DOM node has been rendered. This method + does not alter any values cached in local properties of the + _enyo.Control_ instance. + */ + setNodeProperty: function(inName, inValue) { + if (this.hasNode()) { + this.node[inName] = inValue; + } + }, + /** + Convenience function for setting the _class_ attribute. + The _class_ attribute represents the CSS classes assigned to this object; + it is a string that can contain multiple CSS classes separated by spaces. + + this.$.control.setClassAttribute("box blue-border highlighted"); + */ + setClassAttribute: function(inClass) { + this.setAttribute("class", inClass); + }, + /** + Convenience function for getting the _class_ attribute. + The _class_ attribute represents the CSS classes assigned to this object; + it is a string that can contain multiple CSS classes separated by spaces. + + var cssClasses = this.$.control.getClassAttribute(); + */ + getClassAttribute: function() { + return this.attributes["class"] || ""; + }, + /** + Returns true if the _class_ attribute contains a substring matching + _inClass_. + + The _class_ attribute is a string that can contain multiple CSS classes. + This method tests whether a particular class is part of the set of + classes on this control. + + // returns true if _class_ is "bar foo baz", but false for "barfoobaz" + var hasFooClass = this.$.control.hasClass("foo"); + */ + hasClass: function(inClass) { + return inClass && ((" " + this.getClassAttribute() + " ").indexOf(" " + inClass + " ") >= 0); + }, + /** + Adds CSS class name _inClass_ to the _class_ attribute of this object. + + // add the highlight class to this object + this.addClass("highlight"); + */ + addClass: function(inClass) { + if (inClass && !this.hasClass(inClass)) { + var c = this.getClassAttribute(); + this.setClassAttribute(c + (c ? " " : "") + inClass); + } + }, + /** + Removes substring _inClass_ from the _class_ attribute of this object. + + _inClass_ must have no leading or trailing spaces. + + Using a compound class name is supported, but the name is treated + atomically. For example, given _"a b c"_, _removeClass("a b")_ will + produce _"c"_, but _removeClass("a c")_ will produce _"a b c"_. + + // remove the highlight class from this object + this.removeClass("highlight"); + */ + removeClass: function(inClass) { + if (inClass && this.hasClass(inClass)) { + var c = this.getClassAttribute(); + c = (" " + c + " ").replace(" " + inClass + " ", " ").slice(1, -1); + this.setClassAttribute(c); + } + }, + /** + Adds or removes substring _inClass_ from the _class_ attribute of this + object based on the value of _inTrueToAdd_. + + If _inTrueToAdd_ is truthy, then _inClass_ is added; otherwise, + _inClass_ is removed. + + // add or remove the highlight class, depending on the "highlighted" property + this.addRemoveClass("highlight", this.highlighted); + */ + addRemoveClass: function(inClass, inTrueToAdd) { + this[inTrueToAdd ? "addClass" : "removeClass"](inClass); + }, + // + // styles + // + //* @protected + initStyles: function() { + this.domStyles = this.domStyles || {}; + enyo.Control.cssTextToDomStyles(this.kindStyle, this.domStyles); + this.domCssText = enyo.Control.domStylesToCssText(this.domStyles); + }, + styleChanged: function() { + // FIXME: stomping on domStyles is problematic, there may be styles on this object + // applied by layouts or other objects. + // We may need a 'runtimeStyles' concept separate from a 'userStyles' concept, although + // it's not clear what API calls like 'applyStyle' would affect, and which concept would take + // precedence when there is a conflict. + // Perhaps we can separate 'style' completely from 'domStyles'. API methods like applyStyle + // would affect domStyles, and the two style databases would be combined at render-time. + // Alternatively, we can disallow changing "style" string at runtime and allow it to be set + // at init-time only (as it was in pre-ares enyo). + //this.domStyles = {}; + //this.addStyles(this.kindStyle); + //this.addStyles(this.style); + this.invalidateTags(); + this.renderStyles(); + }, + //* @public + /** + Applies a single style value to this object. + + this.$.box.applyStyle("z-index", 4); + + You may remove a style by setting its value to null. + + this.$.box.applyStyle("z-index", null); + */ + applyStyle: function(inStyle, inValue) { + this.domStyles[inStyle] = inValue; + this.domStylesChanged(); + }, + /** + Adds CSS styles to the set of styles assigned to this object. + + _inCssText_ is a string containing CSS styles in text format. + + this.$.box.addStyles("background-color: red; padding: 4px;"); + */ + addStyles: function(inCssText) { + enyo.Control.cssTextToDomStyles(inCssText, this.domStyles); + this.domStylesChanged(); + }, + /** + Returns the computed value of a CSS style named from _inStyle_ + for the DOM node of the control. If the node hasn't been generated, + returns _inDefault_ as a default value. This uses JavaScript-style + property names, not CSS-style names, so use "fontFamily" instead of + "font-family". + */ + getComputedStyleValue: function(inStyle, inDefault) { + if (this.hasNode()) { + return enyo.dom.getComputedStyleValue(this.node, inStyle); + } + return inDefault; + }, + //* @protected + domStylesChanged: function() { + this.domCssText = enyo.Control.domStylesToCssText(this.domStyles); + this.invalidateTags(); + this.renderStyles(); + }, + stylesToNode: function() { + this.node.style.cssText = this.style + (this.style[this.style.length-1] == ';' ? ' ' : '; ') + this.domCssText; + }, + setupBodyFitting: function() { + enyo.dom.applyBodyFit(); + this.addClass("enyo-fit enyo-clip"); + }, + /* + If the platform is Android or Android-Chrome, don't include + the css rule -webkit-overflow-scrolling: touch, as it is + not supported in Android and leads to overflow issues + (ENYO-900 and ENYO-901) + Similarly, BB10 has issues repainting out-of-viewport content + when -webkit-overflow-scrolling is used (ENYO-1396) + */ + setupOverflowScrolling: function() { + if(enyo.platform.android || enyo.platform.androidChrome || enyo.platform.blackberry) + return; + document.getElementsByTagName("body")[0].className += " webkitOverflowScrolling"; + }, + // + // + //* @public + /** + Renders this object into DOM, generating a DOM node if needed. + */ + render: function() { + if (this.parent) { + // allow the parent to perform setup tasks + // note: ('parent.generated' may change here) + this.parent.beforeChildRender(this); + // don't render if the parent has not generated + if (!this.parent.generated) { + return this; + } + } + if (!this.hasNode()) { + this.renderNode(); + } + if (this.hasNode()) { + this.renderDom(); + if (this.generated) { + this.rendered(); + } + } + // return 'this' to support method chaining + return this; + }, + /** + Renders this object into the DOM node referenced by _inParentNode_. + If rendering into the document body element, appropriate styles will + be used to have it expand to fill the whole window. + */ + renderInto: function(inParentNode) { + // clean up render flags and memoizations + this.teardownRender(); + // inParentNode can be a string id or a node reference + var pn = enyo.dom.byId(inParentNode); + if (pn == document.body) { + this.setupBodyFitting(); + } else if (this.fit) { + this.addClass("enyo-fit enyo-clip"); + } + // for IE10 support, we want full support over touch actions in Enyo-rendered areas + this.addClass("enyo-no-touch-action"); + // add css to enable hw-accelerated scrolling on non-Android platforms (ENYO-900, ENYO-901) + this.setupOverflowScrolling(); + // generate our HTML + enyo.dom.setInnerHtml(pn, this.generateHtml()); + // post-rendering tasks + if (this.generated) { + this.rendered(); + } + // support method chaining + return this; + }, + /** + Uses _document.write_ to output the control into the document. + If the control has _fit: true_ defined, appropriate styles will be set + to have it expand to fill its container. + + Note that this has all the limitations that _document.write_ has. + It only works while the page is loading, so you can't call this from an + event handler. Also, it will not work in certain environments, such as + Chrome Packaged Apps or Windows 8. + */ + write: function() { + if (this.fit) { + this.setupBodyFitting(); + } + // for IE10 support, we want full support over touch actions in Enyo-rendered areas + this.addClass("enyo-no-touch-action"); + // add css to enable hw-accelerated scrolling on non-Android platforms (ENYO-900, ENYO-901) + this.setupOverflowScrolling(); + document.write(this.generateHtml()); + // post-rendering tasks + if (this.generated) { + this.rendered(); + } + // support method chaining + return this; + }, + /** + Override this method to perform tasks that require access to the DOM node. + + rendered: function() { + this.inherited(arguments); + // do some task + } + */ + rendered: function() { + // CAVEAT: Currently we use one entry point ('reflow') for + // post-render layout work *and* post-resize layout work. + this.reflow(); + for (var i=0, c; (c=this.children[i]); i++) { + if (c.generated) { + c.rendered(); + } + } + }, + /** + Shows this node (alias for _setShowing(true)_). + */ + show: function() { + this.setShowing(true); + }, + /** + Hides this node (alias for _setShowing(false)_). + */ + hide: function() { + this.setShowing(false); + }, + /** + Returns an object describing the geometry of this object, like so: + + {left: _offsetLeft_, top: _offsetTop_, width: _offsetWidth_, height: _offsetHeight_} + + Values returned are only valid if _hasNode()_ is truthy. + If there's no DOM node for the object, this returns a bounds structure with + _undefined_ as the value of all fields. + + var bounds = this.getBounds(); + enyo.log(bounds.width); + */ + getBounds: function() { + var n = this.node || this.hasNode(); + var b = enyo.dom.getBounds(n); + return b || {left: undefined, top: undefined, width: undefined, height: undefined}; + }, + /** + Sets any or all of the geometry style properties _width_, _height_, + _left_, _top_, _right_ and _bottom_. + + Values may be specified as strings (with units included), or as numbers + when a unit is provided in _inUnit_. + + this.setBounds({width: 100, height: 100}, "px"); // adds style properties like "width: 100px; height: 100px;" + // + this.setBounds({width: "10em", right: "30pt"}); // adds style properties like "width: 10em; right: 30pt;" + */ + setBounds: function(inBounds, inUnit) { + var s = this.domStyles, unit = inUnit || "px"; + var extents = ["width", "height", "left", "top", "right", "bottom"]; + for (var i=0, b, e; (e=extents[i]); i++) { + b = inBounds[e]; + if (b || b === 0) { + s[e] = b + (!enyo.isString(b) ? unit : ''); + } + } + this.domStylesChanged(); + }, + //* @protected + // expensive, other methods do work to avoid calling here + findNodeById: function() { + return this.id && (this.node = enyo.dom.byId(this.id)); + }, + idChanged: function(inOld) { + if (inOld) { + enyo.Control.unregisterDomEvents(inOld); + } + this.setAttribute("id", this.id); + if (this.id) { + enyo.Control.registerDomEvents(this.id, this); + } + }, + contentChanged: function() { + if (this.hasNode()) { + this.renderContent(); + } + }, + getSrc: function() { + return this.getAttribute("src"); + }, + srcChanged: function() { + this.setAttribute("src", enyo.path.rewrite(this.src)); + }, + attributesChanged: function() { + this.invalidateTags(); + this.renderAttributes(); + }, + // + // HTML rendering + // + generateHtml: function() { + if (this.canGenerate === false) { + return ''; + } + // do this first in case content generation affects outer html (styles or attributes) + var c = this.generateInnerHtml(); + // generate tag, styles, attributes + var h = this.generateOuterHtml(c); + // NOTE: 'generated' is used to gate access to findNodeById in + // hasNode, because findNodeById is expensive. + // NOTE: we typically use 'generated' to mean 'created in DOM' + // but that has not actually happened at this point. + // We set 'generated = true' here anyway to avoid having to walk the + // control tree a second time (to set it later). + // The contract is that insertion in DOM will happen synchronously + // to generateHtml() and before anybody should be calling hasNode(). + this.generated = true; + return h; + }, + generateInnerHtml: function() { + // Flow can alter the way that html content is rendered inside + // the container regardless of whether there are children. + this.flow(); + if (this.children.length) { + return this.generateChildHtml(); + } else { + return this.allowHtml ? this.content : enyo.Control.escapeHtml(this.content); + } + }, + generateChildHtml: function() { + var results = ''; + for (var i=0, c; (c=this.children[i]); i++) { + var h = c.generateHtml(); + results += h; + } + return results; + }, + generateOuterHtml: function(inContent) { + if (!this.tag) { + return inContent; + } + if (!this.tagsValid) { + this.prepareTags(); + } + return this._openTag + inContent + this._closeTag; + }, + invalidateTags: function() { + this.tagsValid = false; + }, + prepareTags: function() { + var htmlStyle = this.domCssText + this.style; + this._openTag = '<' + + this.tag + + (htmlStyle ? ' style="' + htmlStyle + '"' : "") + + enyo.Control.attributesToHtml(this.attributes); + if (enyo.Control.selfClosing[this.tag]) { + this._openTag += '/>'; + this._closeTag = ''; + } else { + this._openTag += '>'; + this._closeTag = ''; + } + this.tagsValid = true; + }, + // DOM, aka direct-to-node, rendering + attributeToNode: function(inName, inValue) { + if (inValue === null || inValue === false || inValue === "") { + this.node.removeAttribute(inName); + } else { + this.node.setAttribute(inName, inValue); + } + }, + attributesToNode: function() { + for (var n in this.attributes) { + this.attributeToNode(n, this.attributes[n]); + } + }, + getParentNode: function() { + return this.parentNode || (this.parent && (this.parent.hasNode() || this.parent.getParentNode())); + }, + addNodeToParent: function() { + if (this.node) { + var pn = this.getParentNode(); + if (pn) { + if (this.addBefore !== undefined) { + this.insertNodeInParent(pn, this.addBefore && this.addBefore.hasNode()); + } else { + this.appendNodeToParent(pn); + } + } + } + }, + appendNodeToParent: function(inParentNode) { + inParentNode.appendChild(this.node); + }, + insertNodeInParent: function(inParentNode, inBeforeNode) { + inParentNode.insertBefore(this.node, inBeforeNode || inParentNode.firstChild); + }, + removeNodeFromDom: function() { + if (this.hasNode() && this.node.parentNode) { + this.node.parentNode.removeChild(this.node); + } + }, + teardownRender: function() { + if (this.generated) { + this.teardownChildren(); + } + this.node = null; + this.generated = false; + }, + teardownChildren: function() { + for (var i=0, c; (c=this.children[i]); i++) { + c.teardownRender(); + } + }, + renderNode: function() { + this.teardownRender(); + this.node = document.createElement(this.tag); + this.addNodeToParent(); + this.generated = true; + }, + renderDom: function() { + this.renderAttributes(); + this.renderStyles(); + this.renderContent(); + }, + renderContent: function() { + if (this.generated) { + this.teardownChildren(); + } + enyo.dom.setInnerHtml(this.node, this.generateInnerHtml()); + }, + renderStyles: function() { + if (this.hasNode()) { + this.stylesToNode(); + } + }, + renderAttributes: function() { + if (this.hasNode()) { + this.attributesToNode(); + } + }, + beforeChildRender: function() { + // if we are generated, we should flow before rendering a child + // if not, the render context isn't ready anyway + if (this.generated) { + this.flow(); + } + }, + syncDisplayToShowing: function() { + var ds = this.domStyles; + if (this.showing) { + // note: only show a node if it's actually hidden + // this way we prevent overriding the value of domStyles.display + if (ds.display == "none") { + this.applyStyle("display", this._displayStyle || ""); + } + } else { + // cache the previous showing value of display + // note: we could use a class to hide a node, but then + // hide would not override a setting of display: none in style, + // which seems bad. + this._displayStyle = (ds.display == "none" ? "" : ds.display); + this.applyStyle("display", "none"); + } + }, + showingChanged: function() { + this.syncDisplayToShowing(); + }, + getShowing: function() { + // 'showing' specifically means domStyles.display !== 'none'. + // 'showing' does not imply the node is actually visible or even rendered in DOM, + // it simply reflects this state of this specific property as a convenience. + return this.showing = (this.domStyles.display != "none"); + }, + // + // + fitChanged: function(inOld) { + this.parent.reflow(); + }, + // + // + statics: { + /** + Returns passed-in string with ampersand, less-than, and greater-than + characters replaced by HTML entities, e.g., + '<code>"This & That"</code>' becomes + '&lt;code&gt;"This &amp; That"&lt;/code&gt;' + */ + escapeHtml: function(inText) { + return inText != null ? String(inText).replace(/&/g,'&').replace(//g,'>') : ''; + }, + //* @protected + registerDomEvents: function(inId, inControl) { + enyo.$[inId] = inControl; + }, + unregisterDomEvents: function(inId) { + enyo.$[inId] = null; + }, + selfClosing: {img: 1, hr: 1, br: 1, area: 1, base: 1, basefont: 1, input: 1, link: 1, meta: 1, + command: 1, embed: 1, keygen: 1, wbr: 1, param: 1, source: 1, track: 1, col: 1}, + cssTextToDomStyles: function(inText, inStyleHash) { + if (inText) { + // remove spaces between rules, then split rules on delimiter (;) + var rules = inText.replace(/; /g, ";").split(";"); + // parse string styles into name/value pairs + for (var i=0, s, n, v, rule; (rule=rules[i]); i++) { + // "background-image: url(http://foo.com/foo.png)" => ["background-image", "url(http", "//foo.com/foo.png)"] + s = rule.split(":"); + // n = "background-image", s = ["url(http", "//foo.com/foo.png)"] + n = s.shift(); + // v = ["url(http", "//foo.com/foo.png)"].join(':') = "url(http://foo.com/foo.png)" + v = s.join(':'); + // store name/value pair + inStyleHash[n] = v; + } + } + }, + domStylesToCssText: function(inStyleHash) { + var n, v, text = ''; + for (n in inStyleHash) { + v = inStyleHash[n]; + if ((v !== null) && (v !== undefined) && (v !== "")) { + text += n + ':' + v + ';'; + } + } + return text; + }, + stylesToHtml: function(inStyleHash) { + var cssText = enyo.Control.domStylesToCssText(inStyleHash); + return (cssText ? ' style="' + cssText + '"' : ""); + }, + /** + Returns passed-in string with ampersand and double quote characters + replaced by HTML entities, e.g., 'hello from "Me & She"' becomes + 'hello from &quot;Me &amp; She&quot;' + */ + escapeAttribute: function(inText) { + return !enyo.isString(inText) ? inText : String(inText).replace(/&/g,'&').replace(/\"/g,'"'); + }, + attributesToHtml: function(inAttributeHash) { + var n, v, h = ''; + for (n in inAttributeHash) { + v = inAttributeHash[n]; + if (v !== null && v !== false && v !== "") { + h += ' ' + n + '="' + enyo.Control.escapeAttribute(v) + '"'; + } + } + return h; + } + } +}); + +enyo.defaultCtor = enyo.Control; + +enyo.Control.subclass = function(ctor, props) { + // Control classes may declare properties that are intended + // to stack with superclass properties. + // + // We resort to prototype magic to assemble these properties + // at kind declaration time, in the interest of efficiency + // and ease of use. + // + // However, the properties are no longer 'live' in prototypes + // because of this magic--i.e., changes to the prototype of + // a Control subclass will not necessarily be reflected in + // instances of that control (e.g., chained prototypes). + // + // These properties are also renamed to kind* to allow + // combining with instance properties. + // + var proto = ctor.prototype; + // + // 'kindClasses' comes either from our inheritance chain (e.g., proto's prototype chain) + // or has been forced by a kind declaration. + // + if (proto.classes) { + var kc = proto.kindClasses; + proto.kindClasses = (kc ? kc + " " : "") + proto.classes; + proto.classes = ""; + } + if (proto.style) { + var ks = proto.kindStyle; + proto.kindStyle = (ks ? ks + ";" : "") + proto.style; + proto.style = ""; + } + if (props.attributes) { + var ka = proto.kindAttributes; + proto.kindAttributes = enyo.mixin(enyo.clone(ka), proto.attributes); + proto.attributes = null; + } +}; diff --git a/enyo/source/dom/animation.js b/enyo/source/dom/animation.js new file mode 100644 index 0000000..13c7af0 --- /dev/null +++ b/enyo/source/dom/animation.js @@ -0,0 +1,99 @@ +(function() { + var ms = Math.round(1000/60); + var prefix = ["webkit", "moz", "ms", "o", ""]; + var r = "requestAnimationFrame"; + var c = "cancel" + enyo.cap(r); + // fallback on setTimeout and clearTimeout + var _requestFrame = function(inCallback) { + return window.setTimeout(inCallback, ms); + }; + var _cancelFrame = function(inId) { + return window.clearTimeout(inId); + }; + for (var i = 0, pl = prefix.length, p, wc, wr; (p = prefix[i]) || i < pl; i++) { + // if we're on ios 6 just use setTimeout, requestAnimationFrame has some kinks currently + if (enyo.platform.ios >= 6) { + break; + } + + // if prefixed, becomes Request and Cancel + wc = p ? (p + enyo.cap(c)) : c; + wr = p ? (p + enyo.cap(r)) : r; + // Test for cancelRequestAnimationFrame, because some browsers (Firefix 4-10) have a request without a cancel + if (window[wc]) { + _cancelFrame = window[wc]; + _requestFrame = window[wr]; + if (p == "webkit") { + /* + Note: In Chrome, the first return value of webkitRequestAnimationFrame is 0. + We make 1 bogus call so the first used return value of webkitRequestAnimationFrame is > 0, as the spec requires. + This makes it so that the requestId is always truthy. + (we choose to do this rather than wrapping the native function to avoid the overhead) + */ + _cancelFrame(_requestFrame(enyo.nop)); + } + break; + } + } + /** + Requests an animation callback. + + On compatible browsers, if _inNode_ is defined, the callback will fire only if _inNode_ is visible. + + Returns a request id to be used with [enyo.cancelRequestAnimationFrame](#enyo.cancelRequestAnimationFrame). + */ + enyo.requestAnimationFrame = function(inCallback, inNode) { + return _requestFrame(inCallback, inNode); + }; + /** + Cancels a requested animation callback with the specified id. + */ + enyo.cancelRequestAnimationFrame = function(inId) { + return _cancelFrame(inId); + }; +})(); + +/** + An assortment of interpolation functions for animations. + + Similar in function to CSS3 transitions. + + Intended for use with [enyo.easedLerp](#enyo.easedLerp) +*/ +enyo.easing = { + cubicIn: function(n) { + return Math.pow(n, 3); + }, + cubicOut: function(n) { + return Math.pow(n - 1, 3) + 1; + }, + expoOut: function(n) { + return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1); + }, + quadInOut: function(n){ + n = n * 2; + if (n < 1) { + return Math.pow(n, 2) / 2; + } + return -1 * ((--n) * (n - 2) - 1) / 2; + }, + linear: function(n) { + return n; + } +}; + +/** + Gives an interpolation of an animated transition's distance from 0 to 1. + + Given a start time (_inT0_) and an animation duration (_inDuration_), applies + the _inEasing_ function to the percentage of time elapsed / duration, capped + at 100%. +*/ +enyo.easedLerp = function(inT0, inDuration, inEasing, reverse) { + var lerp = (enyo.now() - inT0) / inDuration; + if (reverse) { + return lerp >= 1 ? 0 : (1 - inEasing(1 - lerp)); + } else { + return lerp >= 1 ? 1 : inEasing(lerp); + } +}; diff --git a/enyo/source/dom/dispatcher.js b/enyo/source/dom/dispatcher.js new file mode 100644 index 0000000..9b8da00 --- /dev/null +++ b/enyo/source/dom/dispatcher.js @@ -0,0 +1,177 @@ +//* @protected +enyo.$ = {}; + +enyo.dispatcher = { + // these events come from document + events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel", + "click", "dblclick", "change", "keydown", "keyup", "keypress", "input"], + // these events come from window + windowEvents: ["resize", "load", "unload", "message"], + // these events come from css + cssEvents: ["webkitTransitionEnd", "transitionend"], + // feature plugins (aka filters) + features: [], + connect: function() { + var d = enyo.dispatcher, i, n; + for (i=0; (n=d.events[i]); i++) { + d.listen(document, n); + } + for (i=0; (n=d.cssEvents[i]); i++) { + d.listen(document, n); + } + for (i=0; (n=d.windowEvents[i]); i++) { + // Chrome Packaged Apps don't like "unload" + if(n === "unload" && + (typeof window.chrome === "object") && + window.chrome.app) { + continue; + } + + d.listen(window, n); + } + for (i=0; (n=d.cssEvents[i]); i++) { + d.listen(document, n); + } + }, + listen: function(inListener, inEventName, inHandler) { + var d = enyo.dispatch; + if (inListener.addEventListener) { + this.listen = function(inListener, inEventName, inHandler) { + inListener.addEventListener(inEventName, inHandler || d, false); + }; + } else { + //enyo.log("IE8 COMPAT: using 'attachEvent'"); + this.listen = function(inListener, inEvent, inHandler) { + inListener.attachEvent("on" + inEvent, function(e) { + e.target = e.srcElement; + if (!e.preventDefault) { + e.preventDefault = enyo.iePreventDefault; + } + return (inHandler || d)(e); + }); + }; + } + this.listen(inListener, inEventName, inHandler); + }, + //* Fires an event for Enyo to listen for. + dispatch: function(e) { + // Find the control who maps to e.target, or the first control that maps to an ancestor of e.target. + var c = this.findDispatchTarget(e.target) || this.findDefaultTarget(e); + // Cache the original target + e.dispatchTarget = c; + // support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing. + for (var i=0, fn; (fn=this.features[i]); i++) { + if (fn.call(this, e) === true) { + return; + } + } + if (c && !e.preventDispatch) { + this.dispatchBubble(e, c); + } + }, + //* Takes an Event.target and finds the corresponding Enyo control. + findDispatchTarget: function(inNode) { + var t, n = inNode; + // FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context" + // which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if + // it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block. + try { + while (n) { + if ((t = enyo.$[n.id])) { + // there could be multiple nodes with this id, the relevant node for this event is n + // we don't push this directly to t.node because sometimes we are just asking what + // the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut) + t.eventNode = n; + break; + } + n = n.parentNode; + } + } catch(x) { + enyo.log(x, n); + } + return t; + }, + //* Returns the default Enyo control for events. + findDefaultTarget: function(e) { + return enyo.master; + }, + dispatchBubble: function(e, c) { + return c.bubble("on" + e.type, e, c); + } +}; + +// called in the context of an event +enyo.iePreventDefault = function() { + try { + this.returnValue = false; + } + catch(e) { + // do nothing + } +}; + +enyo.dispatch = function(inEvent) { + return enyo.dispatcher.dispatch(inEvent); +}; + +enyo.bubble = function(inEvent) { + // '|| window.event' clause needed for IE8 + var e = inEvent || window.event; + if (e) { + // We depend on e.target existing for event tracking and dispatching. + if (!e.target) { + e.target = e.srcElement; + } + enyo.dispatch(e); + } +}; + +// This string is set on event handlers attributes for DOM elements that +// don't normally bubble (like onscroll) so that they can participate in the +// Enyo event system. +enyo.bubbler = "enyo.bubble(arguments[0])"; + +// The code below helps make Enyo compatible with Google Packages Apps +// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html) +// which, among other things forbids use of inline scripts. +// We replace online scripting with equivalent means, leaving enyo.bubbler +// for backward compatibility. +(function() { + var bubbleUp = function() { + enyo.bubble(arguments[0]); + }; + + /** + * Makes given events bubble on specified enyo contol + */ + enyo.makeBubble = function() { + var args = Array.prototype.slice.call(arguments, 0), + control = args.shift(); + + if((typeof control === "object") && (typeof control.hasNode === "function")) { + enyo.forEach(args, function(event) { + if(this.hasNode()) { + enyo.dispatcher.listen(this.node, event, bubbleUp); + } + }, control); + } + }; +})(); + +// FIXME: we need to create and initialize dispatcher someplace else to allow overrides +enyo.requiresWindow(enyo.dispatcher.connect); + +// generate a tapped event for a raw-click event +enyo.dispatcher.features.push( + function (e) { + if ("click" === e.type) { + if (e.clientX === 0 && e.clientY === 0) { + // this allows the click to dispatch as well + // but note the tap event will fire first + var cp = enyo.clone(e); + cp.type = "tap"; + enyo.dispatch(cp); + } + } + } +); diff --git a/enyo/source/dom/dom.css b/enyo/source/dom/dom.css new file mode 100644 index 0000000..8fa1232 --- /dev/null +++ b/enyo/source/dom/dom.css @@ -0,0 +1,100 @@ +/* things we always want */ +body { + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; +} + +/* allow hw-accelerated scrolling on platforms that support it */ +body.webkitOverflowScrolling { + -webkit-overflow-scrolling: touch; +} + +/* for apps */ +.enyo-document-fit { + margin: 0; + height: 100%; + /* note: giving html overflow: auto is odd and was only ever done to avoid duplication + however, android 4.04 sometimes does not hide nodes when their display is set to none + if document is overflow auto. + */ + position: relative; +} + +.enyo-body-fit { + margin: 0; + height: 100%; + /* helps prevent ios page scroll */ + overflow: auto; + position: relative; +} + +.enyo-no-touch-action { + -ms-touch-action: none; +} + +/* reset */ + +button { + font-size: inherit; + font-family: inherit; +} +button::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* user selection */ + +.enyo-unselectable { + cursor: default; + -ms-user-select: none; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; +} + +.enyo-unselectable::selection, .enyo-unselectable ::selection { + color: transparent; +} + +.enyo-selectable { + cursor: auto; + -ms-user-select: element; + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; +} + +.enyo-selectable::selection, .enyo-selectable ::selection { + background: #3297FD; + color: #FFF; +} + +/* layout */ + +body .enyo-fit { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.enyo-clip { + overflow: hidden; +} + +.enyo-border-box { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* compositing */ + +.enyo-composite { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); +} diff --git a/enyo/source/dom/dom.js b/enyo/source/dom/dom.js new file mode 100644 index 0000000..9679b8d --- /dev/null +++ b/enyo/source/dom/dom.js @@ -0,0 +1,231 @@ +//* @public + +/** + Allow bootstrapping in environments that do not have a window object right away. +*/ +enyo.requiresWindow = function(inFunction) { + inFunction(); +}; + +enyo.dom = { + /** + Shortcut for _document.getElementById_ if _id_ is a string, otherwise returns _id_. + Uses _window.document_ unless a document is specified in the (optional) _doc_ + parameter. + + // find 'node' if it's a string id, or return it unchanged if it's already a node reference + var domNode = enyo.dom.byId(node); + */ + byId: function(id, doc){ + return (typeof id == "string") ? (doc || document).getElementById(id) : id; + }, + /** + return string with ampersand, less-than, and greater-than characters + replaced with HTML entities, e.g. + + '<code>"This & That"</code>' + + becomes + + '&lt;code&gt;"This &amp; That"&lt;/code&gt;' + */ + escape: function(inText) { + return inText !== null ? String(inText).replace(/&/g,'&').replace(//g,'>') : ''; + }, + /** + Returns an object describing the geometry of this node, like so: + + {left: _offsetLeft_, top: _offsetTop_, width: _offsetWidth_, height: _offsetHeight_} + */ + getBounds: function(n) { + if (n) { + return {left: n.offsetLeft, top: n.offsetTop, width: n.offsetWidth, height: n.offsetHeight}; + } + else { + return null; + } + }, + //* @protected + getComputedStyle: function(inNode) { + return window.getComputedStyle && inNode && window.getComputedStyle(inNode, null); + }, + getComputedStyleValue: function(inNode, inProperty, inComputedStyle) { + var s = inComputedStyle || this.getComputedStyle(inNode); + return s ? s.getPropertyValue(inProperty) : null; + }, + getFirstElementByTagName: function(inTagName) { + var e = document.getElementsByTagName(inTagName); + return e && e[0]; + }, + applyBodyFit: function() { + var h = this.getFirstElementByTagName("html"); + if (h) { + h.className += " enyo-document-fit"; + } + var b = this.getFirstElementByTagName("body"); + if (b) { + b.className += " enyo-body-fit"; + } + enyo.bodyIsFitting = true; + }, + getWindowWidth: function() { + if (window.innerWidth) { + return window.innerWidth; + } + if (document.body && document.body.offsetWidth) { + return document.body.offsetWidth; + } + if (document.compatMode=='CSS1Compat' && + document.documentElement && + document.documentElement.offsetWidth ) { + return document.documentElement.offsetWidth; + } + return 320; + }, + getWindowHeight: function() { + if (window.innerHeight) { + return window.innerHeight; + } + if (document.body && document.body.offsetHeight) { + return document.body.offsetHeight; + } + if (document.compatMode=='CSS1Compat' && + document.documentElement && + document.documentElement.offsetHeight ) { + return document.documentElement.offsetHeight; + } + return 480; + }, + // moved from FittableLayout.js into common protected code + _ieCssToPixelValue: function(inNode, inValue) { + var v = inValue; + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + var s = inNode.style; + // store style and runtime style values + var l = s.left; + var rl = inNode.runtimeStyle && inNode.runtimeStyle.left; + // then put current style in runtime style. + if (rl) { + inNode.runtimeStyle.left = inNode.currentStyle.left; + } + // apply given value and measure its pixel value + s.left = v; + v = s.pixelLeft; + // finally restore previous state + s.left = l; + if (rl) { + s.runtimeStyle.left = rl; + } + return v; + }, + _pxMatch: /px/i, + getComputedBoxValue: function(inNode, inProp, inBoundary, inComputedStyle) { + var s = inComputedStyle || this.getComputedStyle(inNode); + if (s) { + return parseInt(s.getPropertyValue(inProp + "-" + inBoundary), 0); + } else if (inNode && inNode.currentStyle) { + var v = inNode.currentStyle[inProp + enyo.cap(inBoundary)]; + if (!v.match(this._pxMatch)) { + v = this._ieCssToPixelValue(inNode, v); + } + return parseInt(v, 0); + } + return 0; + }, + //* @public + //* Gets the boundaries of a node's margin or padding box. + calcBoxExtents: function(inNode, inBox) { + var s = this.getComputedStyle(inNode); + return { + top: this.getComputedBoxValue(inNode, inBox, "top", s), + right: this.getComputedBoxValue(inNode, inBox, "right", s), + bottom: this.getComputedBoxValue(inNode, inBox, "bottom", s), + left: this.getComputedBoxValue(inNode, inBox, "left", s) + }; + }, + //* Gets the calculated padding of a node. + calcPaddingExtents: function(inNode) { + return this.calcBoxExtents(inNode, "padding"); + }, + //* Gets the calculated margin of a node. + calcMarginExtents: function(inNode) { + return this.calcBoxExtents(inNode, "margin"); + }, + /** + Returns an object like `{top: 0, left: 0, bottom: 100, right: 100, height: 10, width: 10}` + that represents the object's position relative to `relativeToNode` (suitable for absolute + positioning within that parent node). Negative values mean part of the object is not visible. + If you leave `relativeToNode` undefined (or it is not a parent element), then the position + will be relative to the viewport and suitable for absolute positioning in a floating layer. + */ + calcNodePosition: function(inNode, relativeToNode) { + // Parse upward and grab our positioning relative to the viewport + var top = 0, + left = 0, + node = inNode, + width = node.offsetWidth, + height = node.offsetHeight, + transformProp = enyo.dom.getStyleTransformProp(), + xregex = /translateX\((-?\d+)px\)/i, + yregex = /translateY\((-?\d+)px\)/i, + borderLeft = 0, borderTop = 0, + totalHeight = 0, totalWidth = 0; + + if (relativeToNode) { + totalHeight = relativeToNode.offsetHeight; + totalWidth = relativeToNode.offsetWidth; + } else { + totalHeight = (document.body.parentNode.offsetHeight > this.getWindowHeight() ? this.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight); + totalWidth = (document.body.parentNode.offsetWidth > this.getWindowWidth() ? this.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth); + } + + if (node.offsetParent) { + do { + left += node.offsetLeft - (node.offsetParent ? node.offsetParent.scrollLeft : 0); + if (transformProp && xregex.test(node.style[transformProp])) { + left += parseInt(node.style[transformProp].replace(xregex, '$1'), 10); + } + top += node.offsetTop - (node.offsetParent ? node.offsetParent.scrollTop : 0); + if (transformProp && yregex.test(node.style[transformProp])) { + top += parseInt(node.style[transformProp].replace(yregex, '$1'), 10); + } + // Need to correct for borders if any exist on parent elements + if (node !== inNode) { + if (node.currentStyle) { + // Oh IE, we do so love working around your incompatibilities + borderLeft = parseInt(node.currentStyle.borderLeftWidth, 10); + borderTop = parseInt(node.currentStyle.borderTopWidth, 10); + } else if (window.getComputedStyle) { + borderLeft = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-left-width'), 10); + borderTop = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-top-width'), 10); + } else { + // No computed style options, so try the normal style object (much less robust) + borderLeft = parseInt(node.style.borderLeftWidth, 10); + borderTop = parseInt(node.style.borderTopWidth, 10); + } + if (borderLeft) { + left += borderLeft; + } + if (borderTop) { + top += borderTop; + } + } + } while ((node = node.offsetParent) && node !== relativeToNode); + } + return { + 'top': top, + 'left': left, + 'bottom': totalHeight - top - height, + 'right': totalWidth - left - width, + 'height': height, + 'width': width + }; + }, + //* use to modify innerHTML in a manner that's safe for Win8 applications + setInnerHtml: function(node, html) { + enyo.execUnsafeLocalFunction(function() { + node.innerHTML = html; + }); + } +}; diff --git a/enyo/source/dom/drag.js b/enyo/source/dom/drag.js new file mode 100644 index 0000000..e7078ef --- /dev/null +++ b/enyo/source/dom/drag.js @@ -0,0 +1,266 @@ +/** + Enyo supports a cross-platform set of drag events. These events allow users + to write a single set of event handlers for applications that run on both + mobile and desktop platforms. + + The following events are provided: + + * "dragstart" + * "dragfinish" + * "drag" + * "drop" + * "dragover" + * "dragout" + * "hold" + * "release" + * "holdpulse" + * "flick" + + For more information on these events, see the documentation on + [User Input](https://github.com/enyojs/enyo/wiki/User-Input) in the Enyo + Developer Guide. +*/ + +//* @protected +enyo.dispatcher.features.push( + function(e) { + // NOTE: beware of properties in enyo.gesture inadvertently mapped to event types + if (enyo.gesture.drag[e.type]) { + return enyo.gesture.drag[e.type](e); + } + } +); + +//* @public +enyo.gesture.drag = { + //* @protected + hysteresisSquared: 16, + holdPulseDelay: 200, + trackCount: 5, + minFlick: 0.1, + minTrack: 8, + down: function(e) { + // tracking if the mouse is down + //enyo.log("tracking ON"); + // Note: 'tracking' flag indicates interest in mousemove, it's turned off + // on mouseup + // make sure to stop dragging in case the up event was not received. + this.stopDragging(e); + this.cancelHold(); + this.target = e.target; + this.startTracking(e); + this.beginHold(e); + }, + move: function(e) { + if (this.tracking) { + this.track(e); + // If the mouse is not down and we're tracking a drag, abort. + // this error condition can occur on IE/Webkit after interaction with a scrollbar. + if (!e.which) { + this.stopDragging(e); + this.cancelHold(); + this.tracking = false; + //enyo.log("enyo.gesture.drag: mouse must be down to drag."); + return; + } + if (this.dragEvent) { + this.sendDrag(e); + } else if (this.dy*this.dy + this.dx*this.dx >= this.hysteresisSquared) { + this.sendDragStart(e); + this.cancelHold(); + } + } + }, + up: function(e) { + this.endTracking(e); + this.stopDragging(e); + this.cancelHold(); + }, + leave: function(e) { + if (this.dragEvent) { + this.sendDragOut(e); + } + }, + stopDragging: function(e) { + if (this.dragEvent) { + this.sendDrop(e); + var handled = this.sendDragFinish(e); + this.dragEvent = null; + return handled; + } + }, + makeDragEvent: function(inType, inTarget, inEvent, inInfo) { + var adx = Math.abs(this.dx), ady = Math.abs(this.dy); + var h = adx > ady; + // suggest locking if off-axis < 22.5 degrees + var l = (h ? ady/adx : adx/ady) < 0.414; + var e = { + type: inType, + dx: this.dx, + dy: this.dy, + ddx: this.dx - this.lastDx, + ddy: this.dy - this.lastDy, + xDirection: this.xDirection, + yDirection: this.yDirection, + pageX: inEvent.pageX, + pageY: inEvent.pageY, + clientX: inEvent.clientX, + clientY: inEvent.clientY, + horizontal: h, + vertical: !h, + lockable: l, + target: inTarget, + dragInfo: inInfo, + ctrlKey: inEvent.ctrlKey, + altKey: inEvent.altKey, + metaKey: inEvent.metaKey, + shiftKey: inEvent.shiftKey, + srcEvent: inEvent.srcEvent + }; + //Fix for IE8, which doesn't include pageX and pageY properties + if(enyo.platform.ie==8 && e.target) { + e.pageX = e.clientX + e.target.scrollLeft; + e.pageY = e.clientY + e.target.scrollTop; + } + e.preventDefault = enyo.gesture.preventDefault; + e.disablePrevention = enyo.gesture.disablePrevention; + return e; + }, + sendDragStart: function(e) { + //enyo.log("dragstart"); + this.dragEvent = this.makeDragEvent("dragstart", this.target, e); + enyo.dispatch(this.dragEvent); + }, + sendDrag: function(e) { + //enyo.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id); + // send dragOver event to the standard event target + var synth = this.makeDragEvent("dragover", e.target, e, this.dragEvent.dragInfo); + enyo.dispatch(synth); + // send drag event to the drag source + synth.type = "drag"; + synth.target = this.dragEvent.target; + enyo.dispatch(synth); + }, + sendDragFinish: function(e) { + //enyo.log("dragfinish"); + var synth = this.makeDragEvent("dragfinish", this.dragEvent.target, e, this.dragEvent.dragInfo); + synth.preventTap = function() { + if (e.preventTap) { + e.preventTap(); + } + }; + enyo.dispatch(synth); + }, + sendDragOut: function(e) { + var synth = this.makeDragEvent("dragout", e.target, e, this.dragEvent.dragInfo); + enyo.dispatch(synth); + }, + sendDrop: function(e) { + var synth = this.makeDragEvent("drop", e.target, e, this.dragEvent.dragInfo); + synth.preventTap = function() { + if (e.preventTap) { + e.preventTap(); + } + }; + enyo.dispatch(synth); + }, + startTracking: function(e) { + this.tracking = true; + // note: use clientX/Y to be compatible with ie8 + this.px0 = e.clientX; + this.py0 = e.clientY; + this.flickInfo = {startEvent: e, moves: []}; + this.track(e); + }, + track: function(e) { + this.lastDx = this.dx; + this.lastDy = this.dy; + this.dx = e.clientX - this.px0; + this.dy = e.clientY - this.py0; + this.xDirection = this.calcDirection(this.dx - this.lastDx, 0); + this.yDirection = this.calcDirection(this.dy - this.lastDy, 0); + // + var ti = this.flickInfo; + ti.moves.push({ + x: e.clientX, + y: e.clientY, + t: enyo.now() + }); + // track specified # of points + if (ti.moves.length > this.trackCount) { + ti.moves.shift(); + } + }, + endTracking: function(e) { + this.tracking = false; + var ti = this.flickInfo; + var moves = ti && ti.moves; + if (moves && moves.length > 1) { + // note: important to use up time to reduce flick + // velocity based on time between move and up. + var l = moves[moves.length-1]; + var n = enyo.now(); + // take the greatest of flick between each tracked move and last move + for (var i=moves.length-2, dt=0, x1=0, y1=0, x=0, y=0, sx=0, sy=0, m; (m=moves[i]); i--) { + // this flick (this move - last move) / (this time - last time) + dt = n - m.t; + x1 = (l.x - m.x) / dt; + y1 = (l.y - m.y) / dt; + // establish flick direction + sx = sx || (x1 < 0 ? -1 : (x1 > 0 ? 1 : 0)); + sy = sy || (y1 < 0 ? -1 : (y1 > 0 ? 1 : 0)); + // if either axis is a greater flick than previously recorded use this one + if ((x1 * sx > x * sx) || (y1 * sy > y * sy)) { + x = x1; + y = y1; + } + } + var v = Math.sqrt(x*x + y*y); + if (v > this.minFlick) { + // generate the flick using the start event so it has those coordinates + this.sendFlick(ti.startEvent, x, y, v); + } + } + this.flickInfo = null; + }, + calcDirection: function(inNum, inDefault) { + return inNum > 0 ? 1 : (inNum < 0 ? -1 : inDefault); + }, + beginHold: function(e) { + this.holdStart = enyo.now(); + this.holdJob = setInterval(enyo.bind(this, "sendHoldPulse", e), this.holdPulseDelay); + }, + cancelHold: function() { + clearInterval(this.holdJob); + this.holdJob = null; + if (this.sentHold) { + this.sentHold = false; + this.sendRelease(this.holdEvent); + } + }, + sendHoldPulse: function(inEvent) { + if (!this.sentHold) { + this.sentHold = true; + this.sendHold(inEvent); + } + var e = enyo.gesture.makeEvent("holdpulse", inEvent); + e.holdTime = enyo.now() - this.holdStart; + enyo.dispatch(e); + }, + sendHold: function(inEvent) { + this.holdEvent = inEvent; + var e = enyo.gesture.makeEvent("hold", inEvent); + enyo.dispatch(e); + }, + sendRelease: function(inEvent) { + var e = enyo.gesture.makeEvent("release", inEvent); + enyo.dispatch(e); + }, + sendFlick: function(inEvent, inX, inY, inV) { + var e = enyo.gesture.makeEvent("flick", inEvent); + e.xVelocity = inX; + e.yVelocity = inY; + e.velocity = inV; + enyo.dispatch(e); + } +}; \ No newline at end of file diff --git a/enyo/source/dom/gesture.js b/enyo/source/dom/gesture.js new file mode 100644 index 0000000..5038fc2 --- /dev/null +++ b/enyo/source/dom/gesture.js @@ -0,0 +1,172 @@ +//* @public +/** + Enyo supports a set of normalized events that work similarly across all + supported platforms. These events are provided so that users can write a + single set of event handlers for applications that run on both mobile and + desktop platforms. They are needed because desktop and mobile platforms + handle basic input differently. + + For more information on normalized input events and their associated + properties, see the documentation on + [User Input](https://github.com/enyojs/enyo/wiki/User-Input) in the Enyo + Developer Guide. +*/ +enyo.gesture = { + //* @protected + eventProps: ["target", "relatedTarget", "clientX", "clientY", "pageX", "pageY", + "screenX", "screenY", "altKey", "ctrlKey", "metaKey", "shiftKey", + "detail", "identifier", "dispatchTarget", "which", "srcEvent"], + makeEvent: function(inType, inEvent) { + var e = {type: inType}; + for (var i=0, p; (p=this.eventProps[i]); i++) { + e[p] = inEvent[p]; + } + e.srcEvent = e.srcEvent || inEvent; + e.preventDefault = this.preventDefault; + e.disablePrevention = this.disablePrevention; + // + // normalize event.which and event.pageX/event.pageY + // Note that while "which" works in IE9, it is broken for mousemove. Therefore, + // in IE, use window.event.button + if (enyo.platform.ie < 10) { + //Fix for IE8, which doesn't include pageX and pageY properties + if(enyo.platform.ie==8 && e.target) { + e.pageX = e.clientX + e.target.scrollLeft; + e.pageY = e.clientY + e.target.scrollTop; + } + var b = window.event && window.event.button; + // multi-button not supported, priority: left, right, middle + // (note: IE bitmask is 1=left, 2=right, 4=center); + e.which = b & 1 ? 1 : (b & 2 ? 2 : (b & 4 ? 3 : 0)); + } else if (enyo.platform.webos || window.PalmSystem) { + // Temporary fix for owos: it does not currently supply 'which' on move events + // and the user agent string doesn't identify itself so we test for PalmSystem + if (e.which === 0) { + e.which = 1; + } + } + return e; + }, + down: function(inEvent) { + // cancel any hold since it's possible in corner cases to get a down without an up + var e = this.makeEvent("down", inEvent); + enyo.dispatch(e); + this.downEvent = e; + }, + move: function(inEvent) { + var e = this.makeEvent("move", inEvent); + // include delta and direction v. down info in move event + e.dx = e.dy = e.horizontal = e.vertical = 0; + if (e.which && this.downEvent) { + e.dx = inEvent.clientX - this.downEvent.clientX; + e.dy = inEvent.clientY - this.downEvent.clientY; + e.horizontal = Math.abs(e.dx) > Math.abs(e.dy); + e.vertical = !e.horizontal; + } + enyo.dispatch(e); + }, + up: function(inEvent) { + var e = this.makeEvent("up", inEvent); + var tapPrevented = false; + e.preventTap = function() { + tapPrevented = true; + }; + enyo.dispatch(e); + if (!tapPrevented && this.downEvent && this.downEvent.which == 1) { + this.sendTap(e); + } + this.downEvent = null; + }, + over: function(inEvent) { + enyo.dispatch(this.makeEvent("enter", inEvent)); + }, + out: function(inEvent) { + enyo.dispatch(this.makeEvent("leave", inEvent)); + }, + sendTap: function(inEvent) { + // The common ancestor for the down/up pair is the origin for the tap event + var t = this.findCommonAncestor(this.downEvent.target, inEvent.target); + if (t) { + var e = this.makeEvent("tap", inEvent); + e.target = t; + enyo.dispatch(e); + } + }, + findCommonAncestor: function(inA, inB) { + var p = inB; + while (p) { + if (this.isTargetDescendantOf(inA, p)) { + return p; + } + p = p.parentNode; + } + }, + isTargetDescendantOf: function(inChild, inParent) { + var c = inChild; + while(c) { + if (c == inParent) { + return true; + } + c = c.parentNode; + } + } +}; + +//* @protected + +// installed on events and called in event context +enyo.gesture.preventDefault = function() { + if (this.srcEvent) { + this.srcEvent.preventDefault(); + } +}; + +enyo.gesture.disablePrevention = function() { + this.preventDefault = enyo.nop; + if (this.srcEvent) { + this.srcEvent.preventDefault = enyo.nop; + } +}; + +enyo.dispatcher.features.push( + function(e) { + // NOTE: beware of properties in enyo.gesture inadvertently mapped to event types + if (enyo.gesture.events[e.type]) { + return enyo.gesture.events[e.type](e); + } + } +); + +enyo.gesture.events = { + mousedown: function(e) { + enyo.gesture.down(e); + }, + mouseup: function(e) { + enyo.gesture.up(e); + }, + mousemove: function(e) { + enyo.gesture.move(e); + }, + mouseover: function(e) { + enyo.gesture.over(e); + }, + mouseout: function(e) { + enyo.gesture.out(e); + } +}; + +// Firefox mousewheel handling +enyo.requiresWindow(function() { + if (document.addEventListener) { + document.addEventListener("DOMMouseScroll", function(inEvent) { + var e = enyo.clone(inEvent); + e.preventDefault = function() { + inEvent.preventDefault(); + }; + e.type = "mousewheel"; + var p = e.VERTICAL_AXIS == e.axis ? "wheelDeltaY" : "wheelDeltaX"; + e[p] = e.detail * -40; + enyo.dispatch(e); + }, false); + } +}); diff --git a/enyo/source/dom/modal.js b/enyo/source/dom/modal.js new file mode 100644 index 0000000..dea4a9e --- /dev/null +++ b/enyo/source/dom/modal.js @@ -0,0 +1,49 @@ +//* @protected + +/** + Event modal capture feature: capture events to a specific + control via enyo.dispatcher.capture(inControl, inShouldForward) + release events via enyo.dispatcher.release() +*/ +enyo.dispatcher.features.push(function(e) { + var c = e.dispatchTarget; + var wants = this.captureTarget && !this.noCaptureEvents[e.type]; + var needs = wants && !(c && c.isDescendantOf && c.isDescendantOf(this.captureTarget)); + if (needs) { + var c1 = e.captureTarget = this.captureTarget; + // NOTE: We do not want releasing capture while an event is being processed to alter + // the way the event propagates. Therefore decide if the event should forward + // before the capture target receives the event (since it may release capture). + var shouldForward = (this.autoForwardEvents[e.type] || this.forwardEvents); + this.dispatchBubble(e, c1); + if (!shouldForward) { + e.preventDispatch = true; + } + } +}); + +// +// NOTE: This object is a plug-in; these methods should +// be called on _enyo.dispatcher_, and not on the plug-in itself. +// +enyo.mixin(enyo.dispatcher, { + noCaptureEvents: {load: 1, unload:1, error: 1}, + autoForwardEvents: {leave: 1, resize: 1}, + captures: [], + //* Capture events for `inTarget` and optionally forward them + capture: function(inTarget, inShouldForward) { + var info = {target: inTarget, forward: inShouldForward}; + this.captures.push(info); + this.setCaptureInfo(info); + }, + //* Release the last captured event + release: function() { + this.captures.pop(); + this.setCaptureInfo(this.captures[this.captures.length-1]); + }, + //* Set the information for a captured event + setCaptureInfo: function(inInfo) { + this.captureTarget = inInfo && inInfo.target; + this.forwardEvents = inInfo && inInfo.forward; + } +}); diff --git a/enyo/source/dom/package.js b/enyo/source/dom/package.js new file mode 100644 index 0000000..d087236 --- /dev/null +++ b/enyo/source/dom/package.js @@ -0,0 +1,15 @@ +enyo.depends( + "dom.css", + "dom.js", + "transform.js", + "Control.js", + "platform.js", + "animation.js", + "phonegap.js", + "dispatcher.js", + "preview.js", + "modal.js", + "gesture.js", + "drag.js", + "transition.js" +); diff --git a/enyo/source/dom/phonegap.js b/enyo/source/dom/phonegap.js new file mode 100644 index 0000000..da86f71 --- /dev/null +++ b/enyo/source/dom/phonegap.js @@ -0,0 +1,46 @@ +/** +Listens for PhoneGap specific events + +Events are exposed through the [Signals](#enyo.Signals) kind by adding callback handlers. + +Example: + +enyo.kind({ + name: "App", + components: [ + {kind: "Signals", ondeviceready: "deviceready"}, + ... + ], + deviceready: function() { + // PhoneGap API exists at this point forward + } +}); + +List of PhoneGap events detailed on the [PhoneGap Docs](http://docs.phonegap.com/en/1.6.0/phonegap_events_events.md.html#Events) +*/ +//* @protected +(function(){ + if (window.cordova || window.PhoneGap) { + var pge = [ + "deviceready", + "pause", + "resume", + "online", + "offline", + "backbutton", + "batterycritical", + "batterylow", + "batterystatus", + "menubutton", + "searchbutton", + "startcallbutton", + "endcallbutton", + "volumedownbutton", + "volumeupbutton" + ]; + for (var i=0, e; (e=pge[i]); i++) { + // some phonegap events have no type, so enyo.dispatch fails + document.addEventListener(e, enyo.bind(enyo.Signals, "send", "on" + e), false); + } + } +})(); diff --git a/enyo/source/dom/platform.js b/enyo/source/dom/platform.js new file mode 100644 index 0000000..d03f392 --- /dev/null +++ b/enyo/source/dom/platform.js @@ -0,0 +1,90 @@ +/** + Determines OS versions of platforms that need special treatment. + Can have one of the following properties: + + * android + * androidChrome (Chrome on Android, standard starting in 4.1) + * androidFirefox + * ie + * ios + * webos + * blackberry + * safari (desktop version) + * chrome (desktop version) + * firefox (desktop version) + + If the property is defined, its value will be the major version number + of the platform. + + Example: + + // android 2 does not have 3d css + if (enyo.platform.android < 3) { + t = "translate(30px, 50px)"; + } else { + t = "translate3d(30px, 50px, 0)"; + } + this.applyStyle("-webkit-transform", t); +*/ +enyo.platform = { + //* True if the platform has native single finger events + touch: Boolean(("ontouchstart" in window) || window.navigator.msMaxTouchPoints), + //* True if the platform has native double finger events + gesture: Boolean(("ongesturestart" in window) || window.navigator.msMaxTouchPoints) +}; + +//* @protected +(function() { + var ua = navigator.userAgent; + var ep = enyo.platform; + var platforms = [ + // Android 4+ using Chrome + {platform: "androidChrome", regex: /Android .* Chrome\/(\d+)[.\d]+/}, + // Android 2 - 4 + {platform: "android", regex: /Android (\d+)/}, + // Kindle Fire + // Force version to 2, (desktop mode does not list android version) + {platform: "android", regex: /Silk\/1./, forceVersion: 2, extra: {silk: 1}}, + // Kindle Fire HD + // Force version to 4 + {platform: "android", regex: /Silk\/2./, forceVersion: 4, extra: {silk: 2}}, + // Windows Phone 7 - 8 + {platform: "windowsPhone", regex: /Windows Phone (?:OS )?(\d+)[.\d]+/}, + // IE 8 - 10 + {platform: "ie", regex: /MSIE (\d+)/}, + // iOS 3 - 5 + // Apple likes to make this complicated + {platform: "ios", regex: /iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/}, + // webOS 1 - 3 + {platform: "webos", regex: /(?:web|hpw)OS\/(\d+)/}, + // desktop Safari + {platform: "safari", regex: /Version\/(\d+)[.\d]+\s+Safari/}, + // desktop Chrome + {platform: "chrome", regex: /Chrome\/(\d+)[.\d]+/}, + // Firefox on Android + {platform: "androidFirefox", regex: /Android;.*Firefox\/(\d+)/}, + // FirefoxOS + {platform: "firefoxOS", regex: /Mobile;.*Firefox\/(\d+)/}, + // desktop Firefox + {platform: "firefox", regex: /Firefox\/(\d+)/}, + // Blackberry 10+ + {platform: "blackberry", regex: /BB1\d;.*Version\/(\d+\.\d+)/} + ]; + for (var i = 0, p, m, v; (p = platforms[i]); i++) { + m = p.regex.exec(ua); + if (m) { + if (p.forceVersion) { + v = p.forceVersion; + } else { + v = Number(m[1]); + } + ep[p.platform] = v; + if (p.extra) { + enyo.mixin(ep, p.extra); + } + break; + } + } + // these platforms only allow one argument for console.log + enyo.dumbConsole = Boolean(ep.android || ep.ios || ep.webos); +})(); \ No newline at end of file diff --git a/enyo/source/dom/preview.js b/enyo/source/dom/preview.js new file mode 100644 index 0000000..4ed1fca --- /dev/null +++ b/enyo/source/dom/preview.js @@ -0,0 +1,36 @@ +/** + Dispatcher preview feature: allow control ancestors of the event + target a chance (eldest first) to react via implementing "previewDomEvent." +*/ +//* @protected +(function() { + var fn = "previewDomEvent"; + // + var preview = { + feature: function(e) { + preview.dispatch(e, e.dispatchTarget); + }, + dispatch: function(e, c) { + var l$ = this.buildLineage(c); + // handlers return true to abort preview and prevent default event processing. + for (var i=0, l; (l=l$[i]); i++) { + if (l[fn] && l[fn](e) === true) { + e.preventDispatch = true; + return; + } + } + }, + // we ascend making a list of enyo controls + // NOTE: the control is considered its own ancestor + buildLineage: function(inControl) { + var l = [], c = inControl; + while (c) { + l.unshift(c); + c = c.parent; + } + return l; + } + }; + // + enyo.dispatcher.features.push(preview.feature); +})(); \ No newline at end of file diff --git a/enyo/source/dom/transform.js b/enyo/source/dom/transform.js new file mode 100644 index 0000000..b42a342 --- /dev/null +++ b/enyo/source/dom/transform.js @@ -0,0 +1,139 @@ +//* @protected +(function() { + enyo.dom.calcCanAccelerate = function() { + /* Android 2 is a liar: it does NOT support 3D transforms, even though Perspective is the best check */ + if (enyo.platform.android <= 2) { + return false; + } + var p$ = ["perspective", "WebkitPerspective", "MozPerspective", "msPerspective", "OPerspective"]; + for (var i=0, p; (p=p$[i]); i++) { + if (typeof document.body.style[p] != "undefined") { + return true; + } + } + return false; + }; + var cssTransformProps = ["transform", "-webkit-transform", "-moz-transform", "-ms-transform", "-o-transform"]; + var styleTransformProps = ["transform", "webkitTransform", "MozTransform", "msTransform", "OTransform"]; + enyo.dom.getCssTransformProp = function() { + if (this._cssTransformProp) { + return this._cssTransformProp; + } + var i = enyo.indexOf(this.getStyleTransformProp(), styleTransformProps); + return this._cssTransformProp = cssTransformProps[i]; + }; + enyo.dom.getStyleTransformProp = function() { + if (this._styleTransformProp || !document.body) { + return this._styleTransformProp; + } + for (var i = 0, p; (p = styleTransformProps[i]); i++) { + if (typeof document.body.style[p] != "undefined") { + return this._styleTransformProp = p; + } + } + }; + enyo.dom.domTransformsToCss = function(inTransforms) { + var n, v, text = ''; + for (n in inTransforms) { + v = inTransforms[n]; + if ((v !== null) && (v !== undefined) && (v !== "")) { + text += n + '(' + v + ') '; + } + } + return text; + }; + enyo.dom.transformsToDom = function(inControl) { + var t = this.domTransformsToCss(inControl.domTransforms); + var st = inControl.hasNode() ? inControl.node.style : null; + var ds = inControl.domStyles; + var sp = this.getStyleTransformProp(); + var cp = this.getCssTransformProp(); + if (sp && cp) { + ds[cp] = t; + if (st) { + st[sp] = t; + } else { + inControl.domStylesChanged(); + } + } + }; + //* @public + /** + Returns true if the platform supports CSS3 Transforms + */ + enyo.dom.canTransform = function() { + return Boolean(this.getStyleTransformProp()); + }; + /** + Returns true if platform supports CSS3 3D Transforms. + + Typically used like this: + + if (enyo.dom.canAccelerate()) { + enyo.dom.transformValue(this.$.slidingThing, "translate3d", x + "," + y + "," + "0") + } else { + enyo.dom.transformValue(this.$.slidingThing, "translate", x + "," + y); + } + + */ + enyo.dom.canAccelerate = function() { + return this.accelerando !== undefined ? this.accelerando: document.body && (this.accelerando = this.calcCanAccelerate()); + }; + /** + Applies a series of transforms to _inControl_, using the platform's prefixed transform property. + + **Note:** Transforms are not commutative, so order is important + + Transform values are updated by successive calls: + + enyo.dom.transform(control, {translate: "30px, 40px", scale: 2, rotate: "20deg"}); + enyo.dom.transform(control, {scale: 3, skewX: "-30deg"}); + + is equivalent to: + + enyo.dom.transform(control, {translate: "30px, 40px", scale: 3, rotate: "20deg", skewX: "-30deg"}); + + When applying these transforms in webkit browser, this is equivalent to: + + control.applyStyle("-webkit-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)"); + + And in firefox, this is equivalent to: + + control.applyStyle("-moz-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)"); + + */ + enyo.dom.transform = function(inControl, inTransforms) { + var d = inControl.domTransforms = inControl.domTransforms || {}; + enyo.mixin(d, inTransforms); + this.transformsToDom(inControl); + }; + + /** + Apply a single transform to _inControl_. + + Example: + + tap: function(inSender, inEvent) { + var c = inEvent.originator; + var r = c.rotation || 0; + r = (r + 45) % 360; + c.rotation = r; + enyo.dom.transformValue(c, "rotate", r); + } + + This will rotate the tapped control by 45 degrees clockwise. + */ + enyo.dom.transformValue = function(inControl, inTransform, inValue) { + var d = inControl.domTransforms = inControl.domTransforms || {}; + d[inTransform] = inValue; + this.transformsToDom(inControl); + }; + //* @protected + /** + Applies a transform that should trigger GPU compositing for _inControl_ + */ + enyo.dom.accelerate = function(inControl, inValue) { + var v = inValue == "auto" ? this.canAccelerate() : inValue; + this.transformValue(inControl, "translateZ", v ? 0 : null); + }; +})(); diff --git a/enyo/source/dom/transition.js b/enyo/source/dom/transition.js new file mode 100644 index 0000000..33affd0 --- /dev/null +++ b/enyo/source/dom/transition.js @@ -0,0 +1,5 @@ +enyo.dom.transition = (enyo.platform.ios || enyo.platform.android || enyo.platform.chrome || enyo.platform.androidChrome || enyo.platform.safari) + ? "-webkit-transition" + : (enyo.platform.firefox || enyo.platform.firefoxOS || enyo.platform.androidFirefox) + ? "-moz-transition" + : "transition"; \ No newline at end of file diff --git a/enyo/source/kernel/Component.js b/enyo/source/kernel/Component.js new file mode 100644 index 0000000..edcd9d5 --- /dev/null +++ b/enyo/source/kernel/Component.js @@ -0,0 +1,547 @@ +/** + _enyo.Component_ is the fundamental building block for Enyo applications. + Components are designed to fit together, so that complex behaviors may be + fashioned from smaller bits of functionality. + + Component constructors take a single argument (sometimes called a + _Component configuration_), a JavaScript object that defines various + properties to be initialized on the Component. For example: + + // create a new component, initialize its name property to 'me'. + var c = new enyo.Component({ + name: "me" + }); + + When a Component is instantiated, items configured in its _components_ + property are instantiated, too: + + // create a new component, which itself has a component + var c = new enyo.Component({ + name: "me", + components: [ + {kind: "Component", name: "other"} + ] + }); + + In this case, when _me_ is created, _other_ is also created, and we say that + _me owns other_. In other words, the _owner_ property of _other_ equals + _me_. Notice that you can specify the _kind_ of _other_ explicitly in its + configuration block, to tell _me_ what constructor to use to create _other_. + + Note that _kind_ values may be references to actual kinds or string-names of + kinds. Kind names that do not resolve directly to kinds are looked up in + default namespaces. In this case, _kind: "Component"_ resolves to + _enyo.Component_. + + To move a component, use the _setOwner_ method to change the component's owner. + If you want to make a component unowned, use _setOwner(null)_. + + If you make changes to _enyo.Component_, be sure to add or update the + appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). + + For more information, see the documentation on + [Components](https://github.com/enyojs/enyo/wiki/Creating-Components) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Component", + kind: enyo.Object, + published: { + /** + A unique name for the component within its owner. This is used to + set the access name in the owner's _$_ hash. If not specified, a + default name will be provided based on the name of the object's + kind, optionally with a number suffix if more than one instance + exists in the owner. + */ + name: "", + /** + A unique id for the component, usually automatically generated based + on its position within the component hierarchy, although it may also + be directly specified. _enyo.Control_ uses this id value for the DOM + id attribute. + */ + id: "", + /** + The component that owns this component. It is usually implicitly + defined during creation based on the _createComponent_ call or + _components_ hash. + */ + owner: null + }, + //* @protected + statics: { + // for memoizing kind-prefix names in nameComponent + _kindPrefixi: {}, + // for naming the unnamed + _unnamedKindNumber: 0 + }, + defaultKind: "Component", + handlers: {}, + toString: function() { + return this.kindName; + }, + constructor: function() { + // initialize instance objects + this._componentNameMap = {}; + this.$ = {}; + this.inherited(arguments); + }, + constructed: function(inProps) { + // entire constructor chain has fired, now start creation chain + // process instance properties + this.importProps(inProps); + // perform initialization + this.create(); + }, + //* @protected + importProps: function(inProps) { + if (inProps) { + for (var n in inProps) { + this[n] = inProps[n]; + } + } + this.handlers = enyo.mixin(enyo.clone(this.kindHandlers), this.handlers); + }, + create: function() { + this.ownerChanged(); + this.initComponents(); + }, + initComponents: function() { + // The _components_ property in kind declarations is renamed to + // _kindComponents_ by the Component subclass mechanism. This makes it + // easy for the developer to distinguish kindComponents from the components + // in _this.components_, without having to worry about the actual difference. + // + // Specifically, the difference is that kindComponents are constructed as + // owned by this control (whereas components in _this.components_ are not). + // In addition, kindComponents are marked with the _isChrome: true_ flag. + this.createChrome(this.kindComponents); + this.createClientComponents(this.components); + }, + createChrome: function(inComponents) { + this.createComponents(inComponents, {isChrome: true}); + }, + createClientComponents: function(inComponents) { + this.createComponents(inComponents, {owner: this.getInstanceOwner()}); + }, + getInstanceOwner: function() { + return (!this.owner || this.owner.notInstanceOwner) ? this : this.owner; + }, + //* @public + /** + Removes this component from its owner (sets _owner_ to null) and does + any cleanup. The component is flagged with a _destroyed: true_ property. + Usually the component will be suitable for garbage collection after + being destroyed, unless user code keeps a reference to it. + */ + destroy: function() { + this.destroyComponents(); + this.setOwner(null); + // JS objects are never truly destroyed (GC'd) until all references are gone, + // we might have some delayed action on this object that needs to have access + // to this flag. + this.destroyed = true; + }, + /** + Destroys all owned components. + */ + destroyComponents: function() { + enyo.forEach(this.getComponents(), function(c) { + // This local components list may be stale as components + // we owned when the loop started could have been destroyed + // by containers. Avoid redestroying components by testing + // destroyed flag. + if (!c.destroyed) { + c.destroy(); + } + }); + }, + //* @protected + makeId: function() { + var delim = "_", pre = this.owner && this.owner.getId(); + var baseName = this.name || ("@@" + (++enyo.Component._unnamedKindNumber)); + return (pre ? pre + delim : "") + baseName; + }, + ownerChanged: function(inOldOwner) { + if (inOldOwner) { + inOldOwner.removeComponent(this); + } + if (this.owner) { + this.owner.addComponent(this); + } + if (!this.id) { + this.id = this.makeId(); + } + //this.id = this.makeId(); + }, + nameComponent: function(inComponent) { + var prefix = enyo.Component.prefixFromKindName(inComponent.kindName); + // get last memoized name index + var n, i = this._componentNameMap[prefix] || 0; + // find an available name + do { + n = prefix + (++i > 1 ? String(i) : ""); + } while (this.$[n]); + // memoize next likely-unique id tag for this prefix + this._componentNameMap[prefix] = Number(i); + // set and return + return inComponent.name = n; + }, + /** + Adds _inComponent_ to the list of components owned by the current + component (i.e., _this.$_). + */ + addComponent: function(inComponent) { + var n = inComponent.getName(); + if (!n) { + n = this.nameComponent(inComponent); + } + if (this.$[n]) { + this.warn('Duplicate component name "' + n + '" in owner "' + this.id + '" violates ' + + 'unique-name-under-owner rule, replacing existing component in the hash and continuing, ' + + 'but this is an error condition and should be fixed.'); + } + this.$[n] = inComponent; + }, + //* Removes _inComponent_ from the list of components owned by the current + //* component (i.e., _this.$_). + removeComponent: function(inComponent) { + delete this.$[inComponent.getName()]; + }, + //* @public + /** + Returns an array of owned components; in other words, converts the _$_ + hash into an array and returns the array. + */ + getComponents: function() { + var results = []; + for (var n in this.$) { + results.push(this.$[n]); + } + return results; + }, + //* @protected + adjustComponentProps: function(inProps) { + if (this.defaultProps) { + enyo.mixin(inProps, this.defaultProps); + } + inProps.kind = inProps.kind || inProps.isa || this.defaultKind; + inProps.owner = inProps.owner || this; + }, + _createComponent: function(inInfo, inMoreInfo) { + if (!inInfo.kind && ("kind" in inInfo)) { + throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + inInfo.name + "]."; + } + // CAVEAT: inInfo and inMoreInfo are copied before mutation, but it's only a shallow copy + var props = enyo.mixin(enyo.clone(inMoreInfo), inInfo); + this.adjustComponentProps(props); + return enyo.Component.create(props); + }, + //* @public + /** + Creates and returns a component as defined by the combination of + _inInfo_ and _inMoreInfo_. Properties in _inInfo_ override properties in + _inMoreInfo_. + + The created component passes through initialization machinery provided + by the creating component, which may supply special handling. + Unless the owner is explicitly specified, the new component will be + owned by the instance on which _createComponent_ is called. + + // Create a new component named _dynamic_ owned by _this_ + // (will be available as this.$.dynamic). + this.createComponent({name: "dynamic"}); + + // Create a new component named _another_ owned by _other_ + // (will be available as other.$.another). + this.createComponent({name: "another"}, {owner: other}); + */ + createComponent: function(inInfo, inMoreInfo) { + // createComponent and createComponents both delegate to the protected method (_createComponent), + // allowing overrides to customize createComponent and createComponents separately. + return this._createComponent(inInfo, inMoreInfo); + }, + /** + Creates Components as defined by the array of configurations _inInfos_. + Each configuration in _inInfos_ is combined with _inCommonInfo_ as + described in _createComponent_. + + _createComponents_ returns an array of references to the created components. + + // ask foo to create components _bar_ and _zot_, but set the owner of + // both components to _this_. + this.$.foo.createComponents([ + {name: "bar"}, + {name: "zot"} + ], {owner: this}); + */ + createComponents: function(inInfos, inCommonInfo) { + if (inInfos) { + var cs = []; + for (var i=0, ci; (ci=inInfos[i]); i++) { + cs.push(this._createComponent(ci, inCommonInfo)); + } + return cs; + } + }, + //* @protected + getBubbleTarget: function() { + return this.owner; + }, + //* @public + /** + Bubbles an event up an object chain, starting with _this_. + + If a handler for this event returns true (aka _handled_), + bubbling is stopped. + + Handlers always have this signature: + + function(inSender, inEvent) + + where _inSender_ refers to the Component that most recently + propagated the event and _inEvent_ is an object containing + event information. + + _inEvent_ will have at least one property, _originator_, which + references the component that triggered the event in the first place. + */ + bubble: function(inEventName, inEvent, inSender) { + var e = inEvent || {}; + // FIXME: is this the right place? + if (!("originator" in e)) { + e.originator = inSender || this; + // FIXME: use indirection here? + //e.delegate = e.originator.delegate || e.originator.owner; + } + return this.dispatchBubble(inEventName, e, inSender); + }, + /** + Bubbles an event up an object chain, starting above _this_. + + If a handler for this event returns true (aka _handled_), + bubbling is stopped. + + Handlers always have this signature: + + function(inSender, inEvent) + + where _inSender_ refers to the Component that most recently + propagated the event and _inEvent_ is an object containing + event information. + + _inEvent_ will have at least one property, _originator_, which + references the component that triggered the event in the first place. + */ + bubbleUp: function(inEventName, inEvent, inSender) { + // Bubble to next target + var next = this.getBubbleTarget(); + if (next) { + return next.dispatchBubble(inEventName, inEvent, this); + } + return false; + }, + //* @protected + /** + Dispatching refers to sending an event to a named delegate. + This object may dispatch an event to itself via a handler, + or to its owner via an event property, e.g.: + + handlers { + // 'tap' events dispatched to this.tapHandler + ontap: "tapHandler" + } + + // 'tap' events dispatched to 'tapHandler' delegate in this.owner + ontap: "tapHandler" + */ + dispatchEvent: function(inEventName, inEvent, inSender) { + // bottleneck event decoration + this.decorateEvent(inEventName, inEvent, inSender); + // + // Note: null checks and sub-expressions are unrolled in this + // high frequency method to reduce call stack in the 90% case. + // These expressions should fail early. + // + // try to dispatch this event directly via handlers + // + if (this.handlers[inEventName] && this.dispatch(this.handlers[inEventName], inEvent, inSender)) { + return true; + } + // + // try to delegate this event to our owner via event properties + // + if (this[inEventName]) { + return this.bubbleDelegation(this.owner, this[inEventName], inEventName, inEvent, this); + } + }, + // internal - try dispatching event to self, if that fails bubble it up the tree + dispatchBubble: function(inEventName, inEvent, inSender) { + // Try to dispatch from here, stop bubbling on truthy return value + if (this.dispatchEvent(inEventName, inEvent, inSender)) { + return true; + } + // Bubble to next target + return this.bubbleUp(inEventName, inEvent, inSender); + }, + decorateEvent: function(inEventName, inEvent, inSender) { + // an event may float by us as part of a dispatchEvent chain or delegateEvent + // both call this method so intermediaries can decorate inEvent + }, + bubbleDelegation: function(inDelegate, inName, inEventName, inEvent, inSender) { + // next target in bubble sequence + var next = this.getBubbleTarget(); + if (next) { + return next.delegateEvent(inDelegate, inName, inEventName, inEvent, inSender); + } + }, + delegateEvent: function(inDelegate, inName, inEventName, inEvent, inSender) { + // override this method to play tricks with delegation + // bottleneck event decoration + this.decorateEvent(inEventName, inEvent, inSender); + // by default, dispatch this event if we are in fact the delegate + if (inDelegate == this) { + return this.dispatch(inName, inEvent, inSender); + } + return this.bubbleDelegation(inDelegate, inName, inEventName, inEvent, inSender); + }, + //* @public + /** + Dispatches the event to named delegate _inMethodName_, if it exists. + Subkinds may re-route dispatches. + Note that both 'handlers' events and events delegated from owned controls + arrive here. If you need to handle these differently, you may + need to also override _dispatchEvent_. + */ + dispatch: function(inMethodName, inEvent, inSender) { + var fn = inMethodName && this[inMethodName]; + if (fn) { + return fn.call(this, inSender || this, inEvent); + } + }, + /** + Sends a message to myself and all of my components. + You can stop a waterfall into components owned by a + receiving object by returning a truthy value from + the event handler. + */ + waterfall: function(inMessageName, inMessage, inSender) { + //this.log(inMessageName, (inSender || this).name, "=>", this.name); + if (this.dispatchEvent(inMessageName, inMessage, inSender)) { + return true; + } + this.waterfallDown(inMessageName, inMessage, inSender || this); + }, + /** + Sends a message to all of my components, but not myself. + You can stop a waterfall into components owned by a + receiving object by returning a truthy value from + the event handler. + */ + waterfallDown: function(inMessageName, inMessage, inSender) { + for (var n in this.$) { + this.$[n].waterfall(inMessageName, inMessage, inSender); + } + } +}); + +//* @protected + +enyo.defaultCtor = enyo.Component; + +// a method to create new instances from config objects. It handles looking up the proper +// constructor based on the provided kind attribute. +enyo.create = enyo.Component.create = function(inConfig) { + if (!inConfig.kind && ("kind" in inConfig)) { + throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + (inConfig.name || "") + "]."; + } + var kind = inConfig.kind || inConfig.isa || enyo.defaultCtor; + var ctor = enyo.constructorForKind(kind); + if (!ctor) { + enyo.error('no constructor found for kind "' + kind + '"'); + ctor = enyo.Component; + } + return new ctor(inConfig); +}; + +enyo.Component.subclass = function(ctor, props) { + // Note: to reduce API surface area, sub-components are declared only as + // 'components' in both kind and instance declarations. + // + // However, 'components' from kind declarations must be handled separately + // at create-time. + // + // We rename the property here to avoid having + // to interrogate the prototype at create-time. + // + var proto = ctor.prototype; + // + if (props.components) { + proto.kindComponents = props.components; + delete proto.components; + } + // + // handlers are merged with supertype handlers + // and kind time. + // + if (props.handlers) { + var kh = proto.kindHandlers; + proto.kindHandlers = enyo.mixin(enyo.clone(kh), proto.handlers); + proto.handlers = null; + } + // events property defines published events for Component kinds + if (props.events) { + this.publishEvents(ctor, props); + } +}; + +enyo.Component.publishEvents = function(ctor, props) { + var es = props.events; + if (es) { + var cp = ctor.prototype; + for (var n in es) { + this.addEvent(n, es[n], cp); + } + } +}; + +enyo.Component.addEvent = function(inName, inValue, inProto) { + var v, fn; + if (!enyo.isString(inValue)) { + v = inValue.value; + fn = inValue.caller; + } else { + if (inName.slice(0, 2) != 'on') { + enyo.warn("enyo.Component.addEvent: event names must start with 'on'. " + inProto.kindName + + " event '" + inName + "' was auto-corrected to 'on" + inName + "'."); + inName = "on" + inName; + } + v = inValue; + fn = "do" + enyo.cap(inName.slice(2)); + } + inProto[inName] = v; + if (!inProto[fn]) { + inProto[fn] = function(inEvent) { + // bubble this event + return this.bubble(inName, inEvent); + }; + // NOTE: Mark this function as a generated event handler to allow us to + // do event chaining. Is this too complicated? + //inProto[fn]._dispatcher = true; + } +}; + +enyo.Component.prefixFromKindName = function(inKindName) { + var prefix = enyo.Component._kindPrefixi[inKindName]; + if (!prefix) { + // memoize naming information for this kind + var l = inKindName.lastIndexOf("."); + prefix = (l >= 0) ? inKindName.slice(l+1) : inKindName; + // lower-case the leading char + prefix = prefix.charAt(0).toLowerCase() + prefix.slice(1); + // memoize result + enyo.Component._kindPrefixi[inKindName] = prefix; + } + return prefix; +}; \ No newline at end of file diff --git a/enyo/source/kernel/Layout.js b/enyo/source/kernel/Layout.js new file mode 100644 index 0000000..d666528 --- /dev/null +++ b/enyo/source/kernel/Layout.js @@ -0,0 +1,34 @@ +/** + _enyo.Layout_ is the base kind for layout kinds. These are used by + enyo.UiComponent-based controls to allow for + arranging of the children by setting the _layoutKind_ property. + + Derived kinds will usually provide their own _layoutClass_ property to + affect the CSS rules used, and may also implement the _flow_ and _reflow_ + methods. _flow_ is called during control rendering, while _reflow_ is called + when the associated control is resized. +*/ +enyo.kind({ + name: "enyo.Layout", + kind: null, + //* CSS class that's added to the control using this layout kind + layoutClass: "", + //* @protected + constructor: function(inContainer) { + this.container = inContainer; + if (inContainer) { + inContainer.addClass(this.layoutClass); + } + }, + destroy: function() { + if (this.container) { + this.container.removeClass(this.layoutClass); + } + }, + // static property layout + flow: function() { + }, + // dynamic measuring layout + reflow: function() { + } +}); diff --git a/enyo/source/kernel/Object.js b/enyo/source/kernel/Object.js new file mode 100644 index 0000000..282b799 --- /dev/null +++ b/enyo/source/kernel/Object.js @@ -0,0 +1,143 @@ +/** +_enyo.Object_ implements the Enyo framework's property publishing system, as +well as providing several utility functions for its subkinds. + +Published properties are declared in a hash called _published_ within a call +to _enyo.kind_. Getter and setter methods are automatically generated for +properties declared in this manner. Also, by convention, the setter for a +published property will trigger an optional _<propertyName>Changed_ method +when called. + +For more information, see the [documentation on Published +Properties](https://github.com/enyojs/enyo/wiki/Published-Properties) in the +Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Object", + //* @protected + // has no base kind + kind: null, + constructor: function() { + enyo._objectCount++; + }, + /** + Sets property named 'n' with value 'v' and then invokes callback + function 'cf' (if specified), passing in the original value of 'n'. + All property setting should bottleneck here so that objects can + observe changes wlog. + */ + setPropertyValue: function(n, v, cf) { + if (this[cf]) { + var old = this[n]; + this[n] = v; + this[cf](old); + } else { + this[n] = v; + } + }, + _setProperty: function(n, v, cf) { + this.setPropertyValue(n, v, (this.getProperty(n) !== v) && cf); + }, + //* @public + //* Destroys object with passed-in name. + destroyObject: function(inName) { + if (this[inName] && this[inName].destroy) { + this[inName].destroy(); + } + this[inName] = null; + }, + //* Gets value of property with passed-in name. + getProperty: function(n) { + var getter = "get" + enyo.cap(n); + if (this[getter]) { + return this[getter](); + } + return this[n]; + }, + //* Sets value of property named 'n' to 'v'. + setProperty: function(n, v) { + var setter = "set" + enyo.cap(n); + if (this[setter]) { + this[setter](v); + } else { + this._setProperty(n, v, n + "Changed"); + } + }, + /** + Sends a log message to the console, prepended with the name of the kind + and method from which _log_ was invoked. Multiple arguments are coerced + to String and joined with spaces. + + enyo.kind({ + name: "MyObject", + kind: enyo.Object, + hello: function() { + this.log("says", "hi"); + // shows in the console: MyObject.hello: says hi + } + }); + */ + log: function() { + var acc = arguments.callee.caller; + var nom = ((acc ? acc.nom : "") || "(instance method)") + ":"; + enyo.logging.log("log", [nom].concat(enyo.cloneArray(arguments))); + }, + //* Same as _log_, except uses the console's warn method (if it exists). + warn: function() { + this._log("warn", arguments); + }, + //* Same as _log_, except uses the console's error method (if it exists). + error: function() { + this._log("error", arguments); + }, + //* @protected + _log: function(inMethod, inArgs) { + if (enyo.logging.shouldLog(inMethod)) { + try { + throw new Error(); + } catch(x) { + enyo.logging._log(inMethod, [inArgs.callee.caller.nom + ": "].concat(enyo.cloneArray(inArgs))); + enyo.log(x.stack); + } + } + } +}); + +//* @protected + +enyo._objectCount = 0; + +enyo.Object.subclass = function(ctor, props) { + this.publish(ctor, props); +}; + +enyo.Object.publish = function(ctor, props) { + var pp = props.published; + if (pp) { + var cp = ctor.prototype; + for (var n in pp) { + enyo.Object.addGetterSetter(n, pp[n], cp); + } + } +}; + +enyo.Object.addGetterSetter = function(inName, inValue, inProto) { + var priv_n = inName; + inProto[priv_n] = inValue; + // + var cap_n = enyo.cap(priv_n); + var get_n = "get" + cap_n; + if (!inProto[get_n]) { + inProto[get_n] = function() { + return this[priv_n]; + }; + } + // + var set_n = "set" + cap_n; + var change_n = priv_n + "Changed"; + if (!inProto[set_n]) { + inProto[set_n] = function(v) { + this._setProperty(priv_n, v, change_n); + }; + } +}; diff --git a/enyo/source/kernel/Oop.js b/enyo/source/kernel/Oop.js new file mode 100644 index 0000000..7e588c4 --- /dev/null +++ b/enyo/source/kernel/Oop.js @@ -0,0 +1,218 @@ +//* @public +/** + Creates a JavaScript constructor function with a prototype defined by + _inProps_. + + _enyo.kind_ makes it easy to build a constructor-with-prototype (like a + class) that has advanced features like prototype-chaining (inheritance). + + A plug-in system is included for extending the abilities of the kind + generator, and constructors are allowed to perform custom operations when + subclassed. + + If you make changes to _enyo.kind_, be sure to add or update the appropriate + [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). + + For more information, see the documentation on + [Creating Kinds](https://github.com/enyojs/enyo/wiki/Creating-Kinds) + in the Enyo Developer Guide. +*/ +enyo.kind = function(inProps) { + // kind-name to constructor map could be faulty now that a new kind exists, so we simply destroy the memoizations + enyo._kindCtors = {}; + // extract 'name' property + var name = inProps.name || ""; + delete inProps.name; + // extract 'kind' property + var hasKind = ("kind" in inProps); + var kind = inProps.kind; + delete inProps.kind; + // establish base class reference + var base = enyo.constructorForKind(kind); + var isa = base && base.prototype || null; + // if we have an explicit kind property with value undefined, we probably + // tried to reference a kind that is not yet in scope + if (hasKind && kind === undefined || base === undefined) { + var problem = kind === undefined ? 'undefined kind' : 'unknown kind (' + kind + ')'; + throw "enyo.kind: Attempt to subclass an " + problem + ". Check dependencies for [" + (name || "") + "]."; + } + // make a boilerplate constructor + var ctor = enyo.kind.makeCtor(); + // semi-reserved word 'constructor' causes problems with Prototype and IE, so we rename it here + if (inProps.hasOwnProperty("constructor")) { + inProps._constructor = inProps.constructor; + delete inProps.constructor; + } + // create our prototype + //ctor.prototype = isa ? enyo.delegate(isa) : {}; + enyo.setPrototype(ctor, isa ? enyo.delegate(isa) : {}); + // put in our props + enyo.mixin(ctor.prototype, inProps); + // alias class name as 'kind' in the prototype + ctor.prototype.kindName = name; + // cache superclass constructor + ctor.prototype.base = base; + // reference our real constructor + ctor.prototype.ctor = ctor; + // support pluggable 'features' + enyo.forEach(enyo.kind.features, function(fn){ fn(ctor, inProps); }); + // put reference into namespace + enyo.setObject(name, ctor); + return ctor; +}; + +/** + Creates a Singleton + + enyo.singleton({ + kind: Control, + name: "app.MySingleton", + published: { + value: "foo" + }, + makeSomething: function() { + //... + } + }); + + app.MySingleton.makeSomething(); + app.MySingleton.setValue("bar"); +*/ +enyo.singleton = function(conf, context) { + // extract 'name' property (the name of our singleton) + var name = conf.name; + delete(conf.name); + // create an unnamed kind and save its constructor's function + var kind = enyo.kind(conf); + // create the singleton with the previous name and constructor + enyo.setObject(name, new kind(), context); +}; + +//* @protected +enyo.kind.makeCtor = function() { + return function() { + if (!(this instanceof arguments.callee)) { + throw "enyo.kind: constructor called directly, not using 'new'"; + } + + // two-pass instantiation + var result; + if (this._constructor) { + // pure construction + result = this._constructor.apply(this, arguments); + } + // defer initialization until entire constructor chain has finished + if (this.constructed) { + // post-constructor initialization + this.constructed.apply(this, arguments); + } + if (result) { + return result; + } + }; +}; + +// classes referenced by name can omit this namespace (e.g. "Button" instead of "enyo.Button") +enyo.kind.defaultNamespace = "enyo"; + +// +// feature hooks for the oop system +// +enyo.kind.features = []; + +// +// 'inherited' feature +// +enyo.kind.features.push(function(ctor, props) { + var proto = ctor.prototype; + if (!proto.inherited) { + proto.inherited = enyo.kind.inherited; + } + if (proto.base) { + // decorate function properties to support inherited (do this ex post facto so that + // ctor.prototype is known, relies on elements in props being copied by reference) + for (var n in props) { + var p = props[n]; + if (enyo.isFunction(p)) { + p._inherited = proto.base.prototype[n] || enyo.nop; + // FIXME: we used to need some extra values for inherited, then inherited got cleaner + // but in the meantime we used these values to support logging in Object. + // For now we support this legacy situation, by suppling logging information here. + p.nom = proto.kindName + '.' + n + '()'; + } + } + } +}); + +enyo.kind.inherited = function(args, newArgs) { + return args.callee._inherited.apply(this, newArgs || args); +}; + +// +// 'statics' feature +// +enyo.kind.features.push(function(ctor, props) { + // install common statics + enyo.mixin(ctor, enyo.kind.statics); + // move props statics to constructor + if (props.statics) { + enyo.mixin(ctor, props.statics); + delete ctor.prototype.statics; + } + // allow superclass customization + var base = ctor.prototype.base; + while (base) { + base.subclass(ctor, props); + base = base.prototype.base; + } +}); + +enyo.kind.statics = { + subclass: function(ctor, props) { + //enyo.log("subclassing [" + ctor.prototype.kind + "] from [", this.prototype.kind + "]"); + }, + extend: function(props) { + enyo.mixin(this.prototype, props); + // support pluggable 'features' + var ctor = this; + enyo.forEach(enyo.kind.features, function(fn){ fn(ctor, props); }); + } +}; + +// +// factory for kinds identified by strings +// +enyo._kindCtors = {}; + +enyo.constructorForKind = function(inKind) { + if (inKind === null || enyo.isFunction(inKind)) { + // in inKind is a function or explicitly null, then that's ctor, full stop. + return inKind; + } + if (inKind) { + // use memoized constructor if available... + var ctor = enyo._kindCtors[inKind]; + if (ctor) { + return ctor; + } + // otherwise look it up and memoize what we find + // + // if inKind is an object in enyo, say "Control", then ctor = enyo["Control"] + // if inKind is a path under enyo, say "Heritage.Button", then ctor = enyo["Heritage.Button"] || enyo.Heritage.Button + // if inKind is a fully qualified path, say "enyo.Heritage.Button", then ctor = enyo["enyo.Heritage.Button"] || enyo.enyo.Heritage.Button || enyo.Heritage.Button + // + // Note that kind "Foo" will resolve to enyo.Foo before resolving to global "Foo". + // This is important so "Image" will map to built-in Image object, instead of enyo.Image control. + return enyo._kindCtors[inKind] = enyo.Theme[inKind] || enyo[inKind] || enyo.getObject(inKind, false, enyo) || window[inKind] || enyo.getObject(inKind); + } + return enyo.defaultCtor; +}; + +// +// namespace for current theme ("enyo.Theme.Button" references the Button specialization for the current theme) +// +enyo.Theme = {}; + +enyo.registerTheme = function(inNamespace) { + enyo.mixin(enyo.Theme, inNamespace); +}; \ No newline at end of file diff --git a/enyo/source/kernel/Signals.js b/enyo/source/kernel/Signals.js new file mode 100644 index 0000000..c3d7500 --- /dev/null +++ b/enyo/source/kernel/Signals.js @@ -0,0 +1,44 @@ +/** + _enyo.Signals_ components are used to listen to global messages. + + An object with a Signals component can listen to messages sent from anywhere + by declaring handlers for them. + + DOM events that have no node targets are broadcast as signals. These events + include Window events, like _onload_ and _onbeforeunload_, and events that + occur directly on _document_, like _onkeypress_ if _document_ has the focus. + + For more information, see the + Signals documentation + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Signals", + kind: enyo.Component, + //* @protected + create: function() { + this.inherited(arguments); + enyo.Signals.addListener(this); + }, + destroy: function() { + enyo.Signals.removeListener(this); + this.inherited(arguments); + }, + notify: function(inMsg, inPayload) { + this.dispatchEvent(inMsg, inPayload); + }, + statics: { + listeners: [], + addListener: function(inListener) { + this.listeners.push(inListener); + }, + removeListener: function(inListener) { + enyo.remove(inListener, this.listeners); + }, + send: function(inMsg, inPayload) { + enyo.forEach(this.listeners, function(l) { + l.notify(inMsg, inPayload); + }); + } + } +}); diff --git a/enyo/source/kernel/UiComponent.js b/enyo/source/kernel/UiComponent.js new file mode 100644 index 0000000..c3f0141 --- /dev/null +++ b/enyo/source/kernel/UiComponent.js @@ -0,0 +1,316 @@ +/** + _enyo.UiComponent_ implements a container strategy suitable for presentation + layers. + + UiComponent itself is abstract. Concrete subkinds include + enyo.Control (for HTML/DOM) and + enyo.canvas.Control + (for Canvas contexts). +*/ +enyo.kind({ + name: "enyo.UiComponent", + kind: enyo.Component, + published: { + //* The UiComponent that physically contains this component in the DOM + container: null, + /** + The UiComponent that owns this component for purposes of event + propagation + */ + parent: null, + /** + The UiComponent that will physically contain new items added by + calls to _createComponent_ + */ + controlParentName: "client", + //* A kind used to manage the size and placement of child components + layoutKind: "" + }, + handlers: { + onresize: "resizeHandler" + }, + /** + When set, provides a control reference used to indicate where a + newly-created component should be added in the UiComponent's array of + children. This is typically used when dynamically creating children + (rather than at design time). If set to null, the new control will be + added at the beginning of the array; if set to a specific existing + control, the new control will be added before the specified control. If + left undefined, the default behavior is to add the new control at the + end of the array. + */ + addBefore: undefined, + //* @protected + statics: { + _resizeFlags: {showingOnly: true} // don't waterfall these events into hidden controls + }, + create: function() { + this.controls = []; + this.children = []; + this.containerChanged(); + this.inherited(arguments); + this.layoutKindChanged(); + }, + destroy: function() { + // Destroys all non-chrome controls (regardless of owner). + this.destroyClientControls(); + // Removes us from our container. + this.setContainer(null); + // Destroys chrome controls owned by this. + this.inherited(arguments); + }, + importProps: function(inProps) { + this.inherited(arguments); + if (!this.owner) { + //this.log("registering ownerless control [" + this.kindName + "] with enyo.master"); + this.owner = enyo.master; + } + }, + // As implemented, _controlParentName_ only works to identify an owned + // control created via _createComponents_ (i.e., usually in our _components_ + // block). To attach a _controlParent_ via other means, one must call + // _discoverControlParent_ or set _controlParent_ directly. + // + // We could call _discoverControlParent_ in _addComponent_, but it would + // cause a lot of useless checking. + createComponents: function() { + var results = this.inherited(arguments); + this.discoverControlParent(); + return results; + }, + discoverControlParent: function() { + this.controlParent = this.$[this.controlParentName] || this.controlParent; + }, + adjustComponentProps: function(inProps) { + // Components we create have us as a container by default. + inProps.container = inProps.container || this; + this.inherited(arguments); + }, + // containment + containerChanged: function(inOldContainer) { + if (inOldContainer) { + inOldContainer.removeControl(this); + } + if (this.container) { + this.container.addControl(this, this.addBefore); + } + }, + // parentage + parentChanged: function(inOldParent) { + if (inOldParent && inOldParent != this.parent) { + inOldParent.removeChild(this); + } + }, + //* @public + // Note: Oddly, a Control is considered a descendant of itself. + isDescendantOf: function(inAncestor) { + var p = this; + while (p && p!=inAncestor) { + p = p.parent; + } + return inAncestor && (p == inAncestor); + }, + /** + Returns all controls. + */ + getControls: function() { + return this.controls; + }, + /** + Returns all non-chrome controls. + */ + getClientControls: function() { + var results = []; + for (var i=0, cs=this.controls, c; (c=cs[i]); i++) { + if (!c.isChrome) { + results.push(c); + } + } + return results; + }, + /** + Destroys "client controls", the same set of controls returned by + _getClientControls_. + */ + destroyClientControls: function() { + var c$ = this.getClientControls(); + for (var i=0, c; (c=c$[i]); i++) { + c.destroy(); + } + }, + //* @protected + addControl: function(inControl, inBefore) { + // Called to add an already created control to the object's control list. It is + // not used to create controls and should likely not be called directly. + // It can be overridden to detect when controls are added. + this.controls.push(inControl); + // When we add a Control, we also establish a parent. + this.addChild(inControl, inBefore); + }, + removeControl: function(inControl) { + // Called to remove a control from the object's control list. As with addControl it + // can be overridden to detect when controls are removed. + // When we remove a Control, we also remove it from its parent. + inControl.setParent(null); + return enyo.remove(inControl, this.controls); + }, + indexOfControl: function(inControl) { + return enyo.indexOf(inControl, this.controls); + }, + indexOfClientControl: function(inControl) { + return enyo.indexOf(inControl, this.getClientControls()); + }, + indexInContainer: function() { + return this.container.indexOfControl(this); + }, + clientIndexInContainer: function() { + return this.container.indexOfClientControl(this); + }, + controlAtIndex: function(inIndex) { + return this.controls[inIndex]; + }, + // children + addChild: function(inChild, inBefore) { + // if inBefore is undefined, add to the end of the child list. + // If it's null, add to front of list, otherwise add before the + // specified control. + // + // allow delegating the child to a different container + if (this.controlParent /*&& !inChild.isChrome*/) { + // this.controlParent might have a controlParent, and so on; seek the ultimate parent + // inBefore is not passed because that control won't be in the controlParent's scope + this.controlParent.addChild(inChild); + } else { + // NOTE: addChild drives setParent. + // It's the opposite for setContainer, where containerChanged (in Containable) + // drives addControl. + // Because of the way 'parent' is derived from 'container', this difference is + // helpful for implementing controlParent. + // By the same token, since 'parent' is derived from 'container', setParent is + // not intended to be called by client code. Therefore, the lack of parallelism + // should be private to this implementation. + // Set the child's parent property to this + inChild.setParent(this); + // track in children array + if (inBefore !== undefined) { + var idx = (inBefore === null) ? 0 : this.indexOfChild(inBefore); + this.children.splice(idx, 0, inChild); + } else { + this.children.push(inChild); + } + } + }, + removeChild: function(inChild) { + return enyo.remove(inChild, this.children); + }, + indexOfChild: function(inChild) { + return enyo.indexOf(inChild, this.children); + }, + layoutKindChanged: function() { + if (this.layout) { + this.layout.destroy(); + } + this.layout = enyo.createFromKind(this.layoutKind, this); + if (this.generated) { + this.render(); + } + }, + flow: function() { + if (this.layout) { + this.layout.flow(); + } + }, + // CAVEAT: currently we use the entry point for both + // post-render layout work *and* post-resize layout work. + reflow: function() { + if (this.layout) { + this.layout.reflow(); + } + }, + /** + Call after this control has been resized to allow it to process the size change. + To respond to a resize, override _resizeHandler_ instead. + */ + // syntactic sugar for 'waterfall("onresize")' + resized: function() { + this.waterfall("onresize", enyo.UiComponent._resizeFlags); + this.waterfall("onpostresize", enyo.UiComponent._resizeFlags); + }, + //* @protected + resizeHandler: function() { + // FIXME: once we are in the business of reflowing layouts on resize, then we have an + // inside/outside problem: some scenarios will need to reflow before child + // controls reflow, and some will need to reflow after. Even more complex scenarios + // have circular dependencies, and can require multiple passes or other resolution. + // When we can rely on CSS to manage reflows we do not have these problems. + this.reflow(); + }, + /** + Sends a message to all my descendents. + */ + waterfallDown: function(inMessage, inPayload, inSender) { + // Note: Controls will generally be both in a $ hash and a child list somewhere. + // Attempt to avoid duplicated messages by sending only to components that are not + // UiComponent, as those components are guaranteed not to be in a child list. + // May cause a problem if there is a scenario where a UiComponent owns a pure + // Component that in turn owns Controls. + // + // waterfall to all pure components + for (var n in this.$) { + if (!(this.$[n] instanceof enyo.UiComponent)) { + this.$[n].waterfall(inMessage, inPayload, inSender); + } + } + // waterfall to my children + for (var i=0, cs=this.children, c; (c=cs[i]); i++) { + // Do not send {showingOnly: true} events to hidden controls. This flag is set for resize events + // which are broadcast from within the framework. This saves a *lot* of unnecessary layout. + // TODO: Maybe remember that we did this, and re-send those messages on setShowing(true)? + // No obvious problems with it as-is, though + if (c.showing || !(inPayload && inPayload.showingOnly)) { + c.waterfall(inMessage, inPayload, inSender); + } + } + }, + getBubbleTarget: function() { + return this.parent; + } +}); + +enyo.createFromKind = function(inKind, inParam) { + var ctor = inKind && enyo.constructorForKind(inKind); + if (ctor) { + return new ctor(inParam); + } +}; + +// +// Default owner for ownerless UiComponents to allow notifying such UiComponents +// of important system events like window resize. +// +// NOTE: Ownerless UiComponents will not be garbage collected unless explicitly +// destroyed, as they will be referenced by _enyo.master_. +// +enyo.master = new enyo.Component({ + name: "master", + notInstanceOwner: true, + eventFlags: {showingOnly: true}, // don't waterfall these events into hidden controls + getId: function() { + return ''; + }, + isDescendantOf: enyo.nop, + bubble: function(inEventName, inEvent, inSender) { + //enyo.log("master event: " + inEventName); + if (inEventName == "onresize") { + // Resize is special; waterfall this message. + // This works because master is a Component, so it waterfalls + // to its owned Components (i.e., master has no children). + enyo.master.waterfallDown("onresize", this.eventFlags); + enyo.master.waterfallDown("onpostresize", this.eventFlags); + } else { + // All other top-level events are sent only to interested Signal + // receivers. + enyo.Signals.send(inEventName, inEvent); + } + } +}); diff --git a/enyo/source/kernel/job.js b/enyo/source/kernel/job.js new file mode 100644 index 0000000..c50b72e --- /dev/null +++ b/enyo/source/kernel/job.js @@ -0,0 +1,33 @@ +/** + Invokes function _inJob_ after _inWait_ milliseconds have elapsed since the + last time _inJobName_ was referenced. + + Jobs can be used to throttle behaviors. If some event may occur once or + multiple times, but we want a response to occur only once every _n_ seconds, + we can use a job. + + onscroll: function() { + // updateThumb will be called, but only when 1s has elapsed since the + // last onscroll + enyo.job("updateThumb", enyo.bind(this, "updateThumb"), 1000); + } +*/ +enyo.job = function(inJobName, inJob, inWait) { + enyo.job.stop(inJobName); + enyo.job._jobs[inJobName] = setTimeout(function() { + enyo.job.stop(inJobName); + inJob(); + }, inWait); +}; + +/** + Cancels the named job, if it has not already fired. +*/ +enyo.job.stop = function(inJobName) { + if (enyo.job._jobs[inJobName]) { + clearTimeout(enyo.job._jobs[inJobName]); + delete enyo.job._jobs[inJobName]; + } +}; + +enyo.job._jobs = {}; \ No newline at end of file diff --git a/enyo/source/kernel/lang.js b/enyo/source/kernel/lang.js new file mode 100644 index 0000000..bb4cd5c --- /dev/null +++ b/enyo/source/kernel/lang.js @@ -0,0 +1,416 @@ +(function(){ + //* @protected + enyo.global = this; + + enyo._getProp = function(parts, create, context) { + var obj = context || enyo.global; + for(var i=0, p; obj && (p=parts[i]); i++){ + obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined)); + } + return obj; + }; + + //* @public + + /** + Sets object _name_ to _value_. _name_ may use dot notation, and + intermediate objects are created as necessary. + + // set foo.bar.baz to 3; if foo or foo.bar do not exist, they are created + enyo.setObject("foo.bar.baz", 3); + + Optionally, _name_ may be relative to object _context_. + + // create foo.zot and set foo.zot.zap to null + enyo.setObject("zot.zap", null, foo); + */ + enyo.setObject = function(name, value, context) { + var parts=name.split("."), p=parts.pop(), obj=enyo._getProp(parts, true, context); + return obj && p ? (obj[p]=value) : undefined; + }; + + /** + Gets object _name_. _name_ may use dot notation. Intermediate objects + are created if the _create_ argument is truthy. + + // get the value of foo.bar, or undefined if foo doesn't exist + var value = enyo.getObject("foo.bar"); + + // get the value of foo.bar; if foo.bar doesn't exist, + // it's assigned an empty object, which is then returned + var value = enyo.getObject("foo.bar", true); + + Optionally, _name_ may be relative to object _context_. + + // get the value of foo.zot.zap, or undefined if foo.zot doesn't exist + var value = enyo.getObject("zot.zap", false, foo); + */ + enyo.getObject = function(name, create, context) { + return enyo._getProp(name.split("."), create, context); + }; + + /** + Returns a random Integer between 0 and _inBound_ (0 <= random integer < _inBound_). + + var randomLetter = String.fromCharCode(enyo.irand(26) + 97); + */ + enyo.irand = function(inBound) { + return Math.floor(Math.random() * inBound); + }; + + //* Returns _inString_ with the first letter capitalized. + enyo.cap = function(inString) { + return inString.slice(0, 1).toUpperCase() + inString.slice(1); + }; + + //* Returns _inString_ with the first letter un-capitalized. + enyo.uncap = function(inString) { + return inString.slice(0, 1).toLowerCase() + inString.slice(1); + }; + + enyo.format = function(inVarArgs) { + var pattern = /\%./g; + var arg = 0, template = inVarArgs, args = arguments; + var replacer = function(inCode) { + return args[++arg]; + }; + return template.replace(pattern, replacer); + }; + + var toString = Object.prototype.toString; + + //* Returns true if _it_ is a string. + enyo.isString = function(it) { + return toString.call(it) === "[object String]"; + }; + + //* Returns true if _it_ is a function. + enyo.isFunction = function(it) { + return toString.call(it) === "[object Function]"; + }; + + //* Returns true if _it_ is an array. + enyo.isArray = Array.isArray || function(it) { + return toString.call(it) === "[object Array]"; + }; + + //* Returns true if the argument is true + enyo.isTrue = function(it) { + return !(it === "false" || it === false || it === 0 || it === null || it === undefined); + }; + + //* Returns the index of the element in _inArray_ that is equivalent (==) to _inElement_, or -1 if no element is found. + enyo.indexOf = function(inElement, inArray, fromIndex) { + if (inArray.indexOf) { + return inArray.indexOf(inElement, fromIndex); + } + + if (fromIndex) { + if (fromIndex < 0) { + fromIndex = 0; + } + + if (fromIndex > inArray.length) { + return -1; + } + } + + for (var i=fromIndex || 0, l=inArray.length, e; (e=inArray[i]) || (i= 0) { + inArray.splice(i, 1); + } + }; + + /** + Invokes _inFunc_ on each element of _inArray_. + If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. + */ + enyo.forEach = function(inArray, inFunc, inContext) { + if (inArray) { + var c = inContext || this; + if (enyo.isArray(inArray) && inArray.forEach) { + inArray.forEach(inFunc, c); + } else { + var a = Object(inArray); + var al = a.length >>> 0; + for (var i = 0; i < al; i++) { + if (i in a) { + inFunc.call(c, a[i], i, a); + } + } + } + } + }; + + /** + Invokes _inFunc_ on each element of _inArray_, and returns the results as an Array. + If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. + */ + enyo.map = function(inArray, inFunc, inContext) { + var c = inContext || this; + if (enyo.isArray(inArray) && inArray.map) { + return inArray.map(inFunc, c); + } else { + var results = []; + var add = function(e, i, a) { + results.push(inFunc.call(c, e, i, a)); + }; + enyo.forEach(inArray, add, c); + return results; + } + }; + + /** + Creates a new array with all elements of _inArray_ that pass the test implemented by _inFunc_. + If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. + */ + enyo.filter = function(inArray, inFunc, inContext) { + var c = inContext || this; + if (enyo.isArray(inArray) && inArray.filter) { + return inArray.filter(inFunc, c); + } else { + var results = []; + var f = function(e, i, a) { + var eo = e; + if (inFunc.call(c, e, i, a)) { + results.push(eo); + } + }; + enyo.forEach(inArray, f, c); + return results; + } + }; + + /** + Returns an array of all own enumerable properties found on _inObject_. + */ + enyo.keys = Object.keys || function(inObject) { + var results = []; + var hop = Object.prototype.hasOwnProperty; + for (var prop in inObject) { + if (hop.call(inObject, prop)) { + results.push(prop); + } + } + // *sigh* IE 8 + if (!({toString: null}).propertyIsEnumerable("toString")) { + var dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ]; + for (var i = 0, p; (p = dontEnums[i]); i++) { + if (hop.call(inObject, p)) { + results.push(p); + } + } + } + return results; + }; + + /** + Clones an existing Array, or converts an array-like object into an Array. + + If _inOffset_ is non-zero, the cloning is started from that index in the source Array. + The clone may be appended to an existing Array by passing the existing Array as _inStartWith_. + + Array-like objects have _length_ properties, and support square-bracket notation ([]). + Often array-like objects do not support Array methods, such as _push_ or _concat_, and + must be converted to Arrays before use. + + The special _arguments_ variable is an example of an array-like object. + */ + enyo.cloneArray = function(inArrayLike, inOffset, inStartWith) { + var arr = inStartWith || []; + for(var i = inOffset || 0, l = inArrayLike.length; ienyo.log will output + if the level is 20 or above, enyo.warn at 10, and + enyo.error at 0. +*/ +enyo.setLogLevel = function(inLevel) { + var ll = parseInt(inLevel, 0); + if (isFinite(ll)) { + enyo.logging.level = ll; + } +}; + +/** + Sends a log message to the console, if the current log level allows for it. + + Objects are converted to JSON automatically. + + Multiple arguments are coerced to String and joined with spaces. +*/ +enyo.log = function() { + enyo.logging.log("log", arguments); +}; + +//* Same as _log_, except uses the console's warn method (if it exists). +enyo.warn = function() { + enyo.logging.log("warn", arguments); +}; + +//* Same as _log_, except uses the console's error method (if it exists). +enyo.error = function() { + enyo.logging.log("error", arguments); +}; \ No newline at end of file diff --git a/enyo/source/kernel/macroize.js b/enyo/source/kernel/macroize.js new file mode 100644 index 0000000..489499b --- /dev/null +++ b/enyo/source/kernel/macroize.js @@ -0,0 +1,74 @@ +//* @public + +/** + Populates a string template with data values. + + Returns a copy of _inText_, with macros defined by _inPattern_ replaced by + named values in _inMap_. + + _inPattern_ may be omitted, in which case the default macro pattern is used. + The default pattern matches macros of the form + + {$name} + + Example: + + // Returns "My name is Barney." + enyo.macroize("My name is {$name}.", {name: "Barney"}); + + Dot notation is supported, like so: + + var info = { + product_0: { + name: "Gizmo" + weight: 3 + } + } + // Returns "Each Gizmo weighs 3 pounds." + enyo.macroize("Each {$product_0.name} weighs {$product_0.weight} pounds.", info); +*/ +enyo.macroize = function(inText, inMap, inPattern) { + var v, working, result = inText, pattern = inPattern || enyo.macroize.pattern; + var fn = function(macro, name) { + v = enyo.getObject(name, false, inMap); + if (v === undefined || v === null) { + return "{$" + name + "}"; + } + working = true; + return v; + }; + var prevent = 0; + do { + working = false; + result = result.replace(pattern, fn); + // if iterating more than 20 times, we assume a recursion (we should probably throw) + if (++prevent >= 20) { + throw("enyo.macroize: recursion too deep"); + } + } while (working); + return result; +}; + +/** + Similar to _enyo.macroize_, but performs only one iteration of the _replace_ + call. This means that recursive expansion of macros isn't possible, but it + avoids the extra processing needed to find recursive use. +*/ +enyo.quickMacroize = function(inText, inMap, inPattern) { + var v, working, result = inText, pattern = inPattern || enyo.macroize.pattern; + var fn = function(macro, name) { + if (name in inMap) { + v = inMap[name]; + } else { + v = enyo.getObject(name, false, inMap); + } + return (v === undefined || v === null) ? "{$" + name + "}" : v; + }; + result = result.replace(pattern, fn); + return result; +}; + +//* @protected + +// Matches macros of the form {$name}. +enyo.macroize.pattern = /\{\$([^{}]*)\}/g; diff --git a/enyo/source/kernel/package.js b/enyo/source/kernel/package.js new file mode 100644 index 0000000..0011420 --- /dev/null +++ b/enyo/source/kernel/package.js @@ -0,0 +1,12 @@ +enyo.depends( + "log.js", + "lang.js", + "job.js", + "macroize.js", + "Oop.js", + "Object.js", + "Component.js", + "UiComponent.js", + "Layout.js", + "Signals.js" +); diff --git a/enyo/source/package.js b/enyo/source/package.js new file mode 100644 index 0000000..ceffe7c --- /dev/null +++ b/enyo/source/package.js @@ -0,0 +1,7 @@ +enyo.depends( + "kernel", + "ajax", + "dom", + "touch", + "ui" +); diff --git a/enyo/source/touch/ScrollMath.js b/enyo/source/touch/ScrollMath.js new file mode 100644 index 0000000..8fb592d --- /dev/null +++ b/enyo/source/touch/ScrollMath.js @@ -0,0 +1,305 @@ +/** +_enyo.ScrollMath_ implements a scrolling dynamics simulation. It is a helper +kind used by other scroller kinds, such as +enyo.TouchScrollStrategy. + +_enyo.ScrollMath_ is not typically created in application code. +*/ +enyo.kind({ + name: "enyo.ScrollMath", + kind: enyo.Component, + published: { + //* True if vertical scrolling is enabled + vertical: true, + //* True if horizontal scrolling is enabled + horizontal: true + }, + events: { + //* Fires when scroll action starts. + onScrollStart: "", + //* Fires while scroll action is in progress. + onScroll: "", + //* Fires when scroll action stops. + onScrollStop: "" + }, + //* 'Spring' damping returns the scroll position to a value inside the + //* boundaries. Lower values provide _faster_ snapback. + kSpringDamping: 0.93, + //* 'Drag' damping resists dragging the scroll position beyond the + //* boundaries. Lower values provide _more_ resistance. + kDragDamping: 0.5, + //* 'Friction' damping reduces momentum over time. Lower values provide + //* _more_ friction. + kFrictionDamping: 0.97, + //* Additional 'friction' damping applied when momentum carries the viewport + //* into overscroll. Lower values provide _more_ friction. + kSnapFriction: 0.9, + //* Scalar applied to 'flick' event velocity + kFlickScalar: 15, + //* Limits the maximum allowable flick. On Android > 2, we limit this to + //* prevent compositing artifacts. + kMaxFlick: enyo.platform.android > 2 ? 2 : 1e9, + //* The value used in friction() to determine if the delta (e.g., y - y0) is + //* close enough to zero to consider as zero + kFrictionEpsilon: 1e-2, + //* Top snap boundary, generally 0 + topBoundary: 0, + //* Right snap boundary, generally (viewport width - content width) + rightBoundary: 0, + //* Bottom snap boundary, generally (viewport height - content height) + bottomBoundary: 0, + //* Left snap boundary, generally 0 + leftBoundary: 0, + //* Animation time step + interval: 20, + //* Flag to enable frame-based animation; if false, time-based animation is used + fixedTime: true, + //* @protected + // simulation state + x0: 0, + x: 0, + y0: 0, + y: 0, + destroy: function() { + this.stop(); + this.inherited(arguments); + }, + /** + Simple Verlet integrator for simulating Newtonian motion. + */ + verlet: function(p) { + var x = this.x; + this.x += x - this.x0; + this.x0 = x; + // + var y = this.y; + this.y += y - this.y0; + this.y0 = y; + }, + /** + Boundary damping function. + Returns damped 'value' based on 'coeff' on one side of 'origin'. + */ + damping: function(value, origin, coeff, sign) { + var kEpsilon = 0.5; + // + // this is basically just value *= coeff (generally, coeff < 1) + // + // 'sign' and the conditional is to force the damping to only occur + // on one side of the origin. + // + var dv = value - origin; + // Force close-to-zero to zero + if (Math.abs(dv) < kEpsilon) { + return origin; + } + return value*sign > origin*sign ? coeff * dv + origin : value; + }, + /** + Dual-boundary damping function. + Returns damped 'value' based on 'coeff' when exceeding either boundary. + */ + boundaryDamping: function(value, aBoundary, bBoundary, coeff) { + return this.damping(this.damping(value, aBoundary, coeff, 1), bBoundary, coeff, -1); + }, + /** + Simulation constraints (spring damping occurs here) + */ + constrain: function() { + var y = this.boundaryDamping(this.y, this.topBoundary, this.bottomBoundary, this.kSpringDamping); + if (y != this.y) { + // ensure snapping introduces no velocity, add additional friction + this.y0 = y - (this.y - this.y0) * this.kSnapFriction; + this.y = y; + } + var x = this.boundaryDamping(this.x, this.leftBoundary, this.rightBoundary, this.kSpringDamping); + if (x != this.x) { + this.x0 = x - (this.x - this.x0) * this.kSnapFriction; + this.x = x; + } + }, + /** + The friction function + */ + friction: function(inEx, inEx0, inCoeff) { + // implicit velocity + var dp = this[inEx] - this[inEx0]; + // let close-to-zero collapse to zero (i.e. smaller than epsilon is considered zero) + var c = Math.abs(dp) > this.kFrictionEpsilon ? inCoeff : 0; + // reposition using damped velocity + this[inEx] = this[inEx0] + c * dp; + }, + // one unit of time for simulation + frame: 10, + // piece-wise constraint simulation + simulate: function(t) { + while (t >= this.frame) { + t -= this.frame; + if (!this.dragging) { + this.constrain(); + } + this.verlet(); + this.friction('y', 'y0', this.kFrictionDamping); + this.friction('x', 'x0', this.kFrictionDamping); + } + return t; + }, + animate: function() { + this.stop(); + // time tracking + var t0 = enyo.now(), t = 0; + // delta tracking + var x0, y0; + // animation handler + var fn = enyo.bind(this, function() { + // wall-clock time + var t1 = enyo.now(); + // schedule next frame + this.job = enyo.requestAnimationFrame(fn); + // delta from last wall clock time + var dt = t1 - t0; + // record the time for next delta + t0 = t1; + // user drags override animation + if (this.dragging) { + this.y0 = this.y = this.uy; + this.x0 = this.x = this.ux; + } + // frame-time accumulator + // min acceptable time is 16ms (60fps) + t += Math.max(16, dt); + // alternate fixed-time step strategy: + if (this.fixedTime && !this.isInOverScroll()) { + t = this.interval; + } + // consume some t in simulation + t = this.simulate(t); + // scroll if we have moved, otherwise the animation is stalled and we can stop + if (y0 != this.y || x0 != this.x) { + //this.log(this.y, y0); + this.scroll(); + } else if (!this.dragging) { + this.stop(true); + this.scroll(); + } + y0 = this.y; + x0 = this.x; + }); + this.job = enyo.requestAnimationFrame(fn); + }, + //* @protected + start: function() { + if (!this.job) { + this.animate(); + this.doScrollStart(); + } + }, + stop: function(inFireEvent) { + this.job = enyo.cancelRequestAnimationFrame(this.job); + if (inFireEvent) { + this.doScrollStop(); + } + }, + stabilize: function() { + this.start(); + var y = Math.min(this.topBoundary, Math.max(this.bottomBoundary, this.y)); + var x = Math.min(this.leftBoundary, Math.max(this.rightBoundary, this.x)); + this.y = this.y0 = y; + this.x = this.x0 = x; + this.scroll(); + this.stop(true); + }, + startDrag: function(e) { + this.dragging = true; + // + this.my = e.pageY; + this.py = this.uy = this.y; + // + this.mx = e.pageX; + this.px = this.ux = this.x; + }, + drag: function(e) { + if (this.dragging) { + var dy = this.vertical ? e.pageY - this.my : 0; + this.uy = dy + this.py; + // provides resistance against dragging into overscroll + this.uy = this.boundaryDamping(this.uy, this.topBoundary, this.bottomBoundary, this.kDragDamping); + // + var dx = this.horizontal ? e.pageX - this.mx : 0; + this.ux = dx + this.px; + // provides resistance against dragging into overscroll + this.ux = this.boundaryDamping(this.ux, this.leftBoundary, this.rightBoundary, this.kDragDamping); + // + this.start(); + return true; + } + }, + dragDrop: function(e) { + if (this.dragging && !window.PalmSystem) { + var kSimulatedFlickScalar = 0.5; + this.y = this.uy; + this.y0 = this.y - (this.y - this.y0) * kSimulatedFlickScalar; + this.x = this.ux; + this.x0 = this.x - (this.x - this.x0) * kSimulatedFlickScalar; + } + this.dragFinish(); + }, + dragFinish: function() { + this.dragging = false; + }, + flick: function(e) { + var v; + if (this.vertical) { + v = e.yVelocity > 0 ? Math.min(this.kMaxFlick, e.yVelocity) : Math.max(-this.kMaxFlick, e.yVelocity); + this.y = this.y0 + v * this.kFlickScalar; + } + if (this.horizontal) { + v = e.xVelocity > 0 ? Math.min(this.kMaxFlick, e.xVelocity) : Math.max(-this.kMaxFlick, e.xVelocity); + this.x = this.x0 + v * this.kFlickScalar; + } + this.start(); + }, + mousewheel: function(e) { + var dy = this.vertical ? e.wheelDeltaY || e.wheelDelta: 0; + if ((dy > 0 && this.y < this.topBoundary) || (dy < 0 && this.y > this.bottomBoundary)) { + this.stop(true); + this.y = this.y0 = this.y0 + dy; + this.start(); + return true; + } + }, + scroll: function() { + this.doScroll(); + }, + // NOTE: Yip/Orvell method for determining scroller instantaneous velocity + // FIXME: incorrect if called when scroller is in overscroll region + // because does not account for additional overscroll damping. + /** + Animates a scroll to the specified position. + */ + scrollTo: function(inX, inY) { + if (inY !== null) { + this.y = this.y0 - (inY + this.y0) * (1 - this.kFrictionDamping); + } + if (inX !== null) { + this.x = this.x0 - (inX + this.x0) * (1 - this.kFrictionDamping); + } + this.start(); + }, + setScrollX: function(inX) { + this.x = this.x0 = inX; + }, + setScrollY: function(inY) { + this.y = this.y0 = inY; + }, + setScrollPosition: function(inPosition) { + this.setScrollY(inPosition); + }, + isScrolling: function() { + return Boolean(this.job); + }, + isInOverScroll: function() { + return this.job && (this.x > this.leftBoundary || this.x < this.rightBoundary || + this.y > this.topBoundary || this.y < this.bottomBoundary); + } +}); diff --git a/enyo/source/touch/ScrollStrategy.js b/enyo/source/touch/ScrollStrategy.js new file mode 100644 index 0000000..4e39207 --- /dev/null +++ b/enyo/source/touch/ScrollStrategy.js @@ -0,0 +1,186 @@ +/** + _enyo.ScrollStrategy_ is a helper kind that implements a default scrolling + strategy for an enyo.Scroller. + + _enyo.ScrollStrategy_ is not typically created in application code. + Instead, it is specified as the value of the `strategyKind` property of an + `enyo.Scroller` or enyo.List, or is used by the + framework implicitly. +*/ +enyo.kind({ + name: "enyo.ScrollStrategy", + tag: null, + published: { + /** + Specifies how to vertically scroll. Acceptable values are: + + * "scroll": Always shows a scrollbar; sets _overflow: scroll_. + * "auto": Scrolls only if needed; sets _overflow: auto_. + * "hidden": Never scrolls; sets _overflow: hidden_. + * "default": Same as "auto". + */ + vertical: "default", + /** + Specifies how to horizontally scroll. Acceptable values are: + + * "scroll": Always shows a scrollbar; sets _overflow: scroll_. + * "auto": Scrolls only if needed; sets _overflow: auto_. + * "hidden": Never scrolls; sets _overflow: hidden_. + * "default": Same as "auto". + */ + horizontal: "default", + //* Scroll position along horizontal axis + scrollLeft: 0, + //* Scroll position along vertical axis + scrollTop: 0, + //* Maximum height of scroll content + maxHeight: null + }, + //* @protected + handlers: { + ondragstart: "dragstart", + ondragfinish: "dragfinish", + ondown: "down", + onmove: "move" + }, + create: function() { + this.inherited(arguments); + this.horizontalChanged(); + this.verticalChanged(); + this.maxHeightChanged(); + }, + rendered: function() { + this.inherited(arguments); + enyo.makeBubble(this.container, "scroll"); + this.scrollNode = this.calcScrollNode(); + }, + teardownRender: function() { + this.inherited(arguments); + this.scrollNode = null; + }, + calcScrollNode: function() { + return this.container.hasNode(); + }, + horizontalChanged: function() { + this.container.applyStyle("overflow-x", this.horizontal == "default" ? "auto" : this.horizontal); + }, + verticalChanged: function() { + this.container.applyStyle("overflow-y", this.vertical == "default" ? "auto" : this.vertical); + }, + maxHeightChanged: function() { + this.container.applyStyle("max-height", this.maxHeight); + }, + scrollTo: function(inX, inY) { + if (this.scrollNode) { + this.setScrollLeft(inX); + this.setScrollTop(inY); + } + }, + scrollToNode: function(inNode, inAlignWithTop) { + if (this.scrollNode) { + var sb = this.getScrollBounds(); + var n = inNode; + var b = {height: n.offsetHeight, width: n.offsetWidth, top: 0, left: 0}; + while (n && n.parentNode && n.id != this.scrollNode.id) { + b.top += n.offsetTop; + b.left += n.offsetLeft; + n = n.parentNode; + } + // By default, the element is scrolled to align with the top of the scroll area. + this.setScrollTop(Math.min(sb.maxTop, inAlignWithTop === false ? b.top - sb.clientHeight + b.height : b.top)); + this.setScrollLeft(Math.min(sb.maxLeft, inAlignWithTop === false ? b.left - sb.clientWidth + b.width : b.left)); + } + }, + scrollIntoView: function(inControl, inAlignWithTop) { + if (inControl.hasNode()) { + inControl.node.scrollIntoView(inAlignWithTop); + } + }, + isInView: function(inNode) { + var sb = this.getScrollBounds(); + var ot = inNode.offsetTop; + var oh = inNode.offsetHeight; + var ol = inNode.offsetLeft; + var ow = inNode.offsetWidth; + return (ot >= sb.top && ot + oh <= sb.top + sb.clientHeight) && (ol >= sb.left && ol + ow <= sb.left + sb.clientWidth); + }, + setScrollTop: function(inTop) { + this.scrollTop = inTop; + if (this.scrollNode) { + this.scrollNode.scrollTop = this.scrollTop; + } + }, + setScrollLeft: function(inLeft) { + this.scrollLeft = inLeft; + if (this.scrollNode) { + this.scrollNode.scrollLeft = this.scrollLeft; + } + }, + getScrollLeft: function() { + return this.scrollNode ? this.scrollNode.scrollLeft : this.scrollLeft; + }, + getScrollTop: function() { + return this.scrollNode ? this.scrollNode.scrollTop : this.scrollTop; + }, + _getScrollBounds: function() { + var s = this.getScrollSize(), cn = this.container.hasNode(); + var b = { + left: this.getScrollLeft(), + top: this.getScrollTop(), + clientHeight: cn ? cn.clientHeight : 0, + clientWidth: cn ? cn.clientWidth : 0, + height: s.height, + width: s.width + }; + b.maxLeft = Math.max(0, b.width - b.clientWidth); + b.maxTop = Math.max(0, b.height - b.clientHeight); + return b; + }, + getScrollSize: function() { + var n = this.scrollNode; + return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; + }, + getScrollBounds: function() { + return this._getScrollBounds(); + }, + calcStartInfo: function() { + var sb = this.getScrollBounds(); + var y = this.getScrollTop(), x = this.getScrollLeft(); + this.canVertical = sb.maxTop > 0 && this.vertical != "hidden"; + this.canHorizontal = sb.maxLeft > 0 && this.horizontal != "hidden"; + this.startEdges = { + top: y === 0, + bottom: y === sb.maxTop, + left: x === 0, + right: x === sb.maxLeft + }; + }, + // NOTE: down, move, and drag handlers are needed only for native touch scrollers + shouldDrag: function(inEvent) { + var requestV = inEvent.vertical; + return (requestV && this.canVertical || !requestV && this.canHorizontal) /*&& !this.isOobVerticalScroll(inEvent)*/; + }, + dragstart: function(inSender, inEvent) { + this.dragging = this.shouldDrag(inEvent); + if (this.dragging) { + return this.preventDragPropagation; + } + }, + dragfinish: function(inSender, inEvent) { + if (this.dragging) { + this.dragging = false; + inEvent.preventTap(); + } + }, + // avoid allowing scroll when starting at a vertical boundary to prevent ios from window scrolling. + down: function(inSender, inEvent) { + this.calcStartInfo(); + }, + // NOTE: mobile native scrollers need touchmove. Indicate this by + // setting the requireTouchmove property to true. + move: function(inSender, inEvent) { + if (inEvent.which && (this.canVertical && inEvent.vertical || this.canHorizontal && inEvent.horizontal)) { + inEvent.disablePrevention(); + } + } +}); \ No newline at end of file diff --git a/enyo/source/touch/Scroller.css b/enyo/source/touch/Scroller.css new file mode 100644 index 0000000..2390c92 --- /dev/null +++ b/enyo/source/touch/Scroller.css @@ -0,0 +1,19 @@ +.enyo-scroller { + position: relative; +} + +.enyo-fit.enyo-scroller { + position: absolute; +} + +.enyo-touch-scroller { + overflow: hidden; +} + +.enyo-touch-strategy-container { + overflow: hidden; +} + +.enyo-scrollee-fit { + height: 100%; +} \ No newline at end of file diff --git a/enyo/source/touch/Scroller.js b/enyo/source/touch/Scroller.js new file mode 100644 index 0000000..81f69d5 --- /dev/null +++ b/enyo/source/touch/Scroller.js @@ -0,0 +1,344 @@ +/** +_enyo.Scroller_ is a scroller suitable for use in both desktop and mobile +applications. + +In some mobile environments, a default scrolling solution is not implemented for +DOM elements. In such cases, _enyo.Scroller_ implements a touch-based scrolling +solution, which may be opted into either globally (by setting the flag +_enyo.Scroller.touchScrolling = true;_) or on a per-instance basis (by +specifying a _strategyKind_ of "TouchScrollStrategy"). + +For more information, see the documentation on +[Scrollers](https://github.com/enyojs/enyo/wiki/Scrollers) in the Enyo Developer +Guide. +*/ +enyo.kind({ + name: "enyo.Scroller", + published: { + /** + Specifies how to horizontally scroll. Acceptable values are + "scroll", "auto," "hidden," and "default". The precise + effect of the setting is determined by the scroll strategy. + */ + horizontal: "default", + /** + Specifies how to vertically scroll. Acceptable values are "scroll", + "auto," "hidden," and "default". The precise effect of the setting + is determined by the scroll strategy. + */ + vertical: "default", + /** + The vertical scroll position + */ + scrollTop: 0, + /** + The horizontal scroll position + */ + scrollLeft: 0, + /** + Maximum height of the scroll content + */ + maxHeight: null, + /** + Set to true to make this scroller select a platform-appropriate + touch-based scrolling strategy. Note that if you specify a value for + _strategyKind_, that will take precedence over this setting. + */ + touch: false, + /** + Specifies a type of scrolling. The scroller will attempt to + automatically select a strategy compatible with the runtime + environment. Alternatively, you may choose to use a specific + strategy: + + * ScrollStrategy is the default + and implements no scrolling, relying instead on the environment + to scroll properly. + + * TouchScrollStrategy + implements a touch scrolling mechanism. + + * TranslateScrollStrategy + implements a touch scrolling mechanism using translations; it is + currently recommended only for Android 3 and 4 & Windows Phone 8. + + * TransitionScrollStrategy + implements a touch scrolling mechanism using CSS transitions; it is + currently recommended only for iOS 5 and later. + */ + strategyKind: "ScrollStrategy", + //* Set to true to display a scroll thumb in touch scrollers + thumb: true + }, + events: { + //* Fires when a scrolling action starts. + onScrollStart: "", + //* Fires while a scrolling action is in progress. + onScroll: "", + //* Fires when a scrolling action stops. + onScrollStop: "" + }, + /** + If true (the default) and a touch scroller, the scroller will overscroll + and bounce back at the edges + */ + touchOverscroll: true, + /** + If true (the default), the scroller will not propagate _dragstart_ + events that cause it to start scrolling + */ + preventDragPropagation: true, + /** + If true, the scroller will not propagate scroll events + */ + preventScrollPropagation: true, + //* @protected + handlers: { + onscroll: "domScroll", + onScrollStart: "scrollStart", + onScroll: "scroll", + onScrollStop: "scrollStop" + }, + classes: "enyo-scroller", + statics: { + osInfo: [ + {os: "android", version: 3}, + {os: "androidChrome", version: 18}, + {os: "androidFirefox", version: 16}, + {os: "firefoxOS", version: 16}, + {os: "ios", version: 5}, + {os: "webos", version: 1e9}, + {os: "blackberry", version:1e9} + ], + //* Returns true if platform should have touch events. + hasTouchScrolling: function() { + for (var i=0, t, m; (t=this.osInfo[i]); i++) { + if (enyo.platform[t.os]) { + return true; + } + } + // special detection for IE10+ on touch devices + if ((enyo.platform.ie >= 10 || enyo.platform.windowsPhone >= 8) && enyo.platform.touch) { + return true; + } + }, + /** + Returns true if the platform has native div scrollers (desktop + browsers always have them). + */ + hasNativeScrolling: function() { + for (var i=0, t, m; (t=this.osInfo[i]); i++) { + if (enyo.platform[t.os] < t.version) { + return false; + } + } + return true; + }, + getTouchStrategy: function() { + return (enyo.platform.android >= 3) || (enyo.platform.windowsPhone === 8) + ? "TranslateScrollStrategy" + : "TouchScrollStrategy"; + } + }, + controlParentName: "strategy", + create: function() { + this.inherited(arguments); + this.horizontalChanged(); + this.verticalChanged(); + }, + importProps: function(inProps) { + this.inherited(arguments); + // allow global overriding of strategy kind + if (inProps && inProps.strategyKind === undefined && (enyo.Scroller.touchScrolling || this.touch)) { + this.strategyKind = enyo.Scroller.getTouchStrategy(); + } + }, + initComponents: function() { + this.strategyKindChanged(); + this.inherited(arguments); + }, + teardownChildren: function() { + this.cacheScrollPosition(); + this.inherited(arguments); + }, + rendered: function() { + this.inherited(arguments); + this.restoreScrollPosition(); + }, + strategyKindChanged: function() { + if (this.$.strategy) { + this.$.strategy.destroy(); + this.controlParent = null; + } + // note: createComponents automatically updates controlParent. + this.createStrategy(); + if (this.hasNode()) { + this.render(); + } + }, + createStrategy: function() { + this.createComponents([{name: "strategy", maxHeight: this.maxHeight, + kind: this.strategyKind, thumb: this.thumb, + preventDragPropagation: this.preventDragPropagation, + overscroll:this.touchOverscroll, isChrome: true}]); + }, + getStrategy: function() { + return this.$.strategy; + }, + maxHeightChanged: function() { + this.$.strategy.setMaxHeight(this.maxHeight); + }, + showingChanged: function() { + if (!this.showing) { + this.cacheScrollPosition(); + this.setScrollLeft(0); + this.setScrollTop(0); + } + this.inherited(arguments); + if (this.showing) { + this.restoreScrollPosition(); + } + }, + thumbChanged: function() { + this.$.strategy.setThumb(this.thumb); + }, + cacheScrollPosition: function() { + this.cachedPosition = {left: this.getScrollLeft(), top: this.getScrollTop()}; + }, + restoreScrollPosition: function() { + if (this.cachedPosition) { + this.setScrollLeft(this.cachedPosition.left); + this.setScrollTop(this.cachedPosition.top); + this.cachedPosition = null; + } + }, + horizontalChanged: function() { + this.$.strategy.setHorizontal(this.horizontal); + }, + verticalChanged: function() { + this.$.strategy.setVertical(this.vertical); + }, + // FIXME: these properties are virtual; property changed methods are fired only if + // property value changes, not if getter changes. + //* Sets scroll position along horizontal axis. + setScrollLeft: function(inLeft) { + this.scrollLeft = inLeft; + this.$.strategy.setScrollLeft(this.scrollLeft); + }, + //* Sets scroll position along vertical axis. + setScrollTop: function(inTop) { + this.scrollTop = inTop; + this.$.strategy.setScrollTop(inTop); + }, + //* Gets scroll position along horizontal axis. + getScrollLeft: function() { + return this.$.strategy.getScrollLeft(); + }, + //* Gets scroll position along vertical axis. + getScrollTop: function() { + return this.$.strategy.getScrollTop(); + }, + //* @public + /** + Returns an object describing the scroll boundaries with _height_ and + _width_ properties. + */ + getScrollBounds: function() { + return this.$.strategy.getScrollBounds(); + }, + /** + Scrolls the given control (_inControl_) into view. If _inAlignWithTop_ + is true, _inControl_ is aligned with the top of the scroller. + */ + scrollIntoView: function(inControl, inAlignWithTop) { + this.$.strategy.scrollIntoView(inControl, inAlignWithTop); + }, + //* Scrolls to the position specified by _inX_ and _inY_ in pixel units. + scrollTo: function(inX, inY) { + this.$.strategy.scrollTo(inX, inY); + }, + /** + Ensures that the given control is visible in the scroller's viewport. + Unlike _scrollIntoView_, which uses DOM's _scrollIntoView_, this only + affects the current scroller. + */ + scrollToControl: function(inControl, inAlignWithTop) { + this.scrollToNode(inControl.hasNode(), inAlignWithTop); + }, + //* Ensures that the given node is visible in the scroller's viewport. + scrollToNode: function(inNode, inAlignWithTop) { + this.$.strategy.scrollToNode(inNode, inAlignWithTop); + }, + //* @protected + //* Normalizes scroll event to _onScroll_. + domScroll: function(inSender, e) { + // if a scroll event originated here, pass it to our strategy to handle + if (this.$.strategy.domScroll && e.originator == this) { + this.$.strategy.scroll(inSender, e); + } + this.doScroll(e); + return true; + }, + /** + Returns true if the current scroll event should be stopped; false if it + should be allowed to propagate. + */ + shouldStopScrollEvent: function(inEvent) { + return (this.preventScrollPropagation && + inEvent.originator.owner != this.$.strategy); + }, + /** + Calls _shouldStopScrollEvent_ to determine whether current scroll event + should be stopped. + */ + scrollStart: function(inSender, inEvent) { + return this.shouldStopScrollEvent(inEvent); + }, + //* Either propagates or stops the current scroll event. + scroll: function(inSender, inEvent) { + // note: scroll event can be native dom or generated. + if (inEvent.dispatchTarget) { + // allow a dom event if it orignated with this scroller or its strategy + return this.preventScrollPropagation && !(inEvent.originator == this || + inEvent.originator.owner == this.$.strategy); + } else { + return this.shouldStopScrollEvent(inEvent); + } + }, + /** + Calls _shouldStopScrollEvent_ to determine whether current scroll event + should be stopped. + */ + scrollStop: function(inSender, inEvent) { + return this.shouldStopScrollEvent(inEvent); + }, + //* @public + //* Scroll to the top of the scrolling region. + scrollToTop: function() { + this.setScrollTop(0); + }, + //* Scroll to the bottom of the scrolling region. + scrollToBottom: function() { + this.setScrollTop(this.getScrollBounds().maxTop); + }, + //* Scroll to the right edge of the scrolling region. + scrollToRight: function() { + this.setScrollLeft(this.getScrollBounds().maxLeft); + }, + //* Scroll to the left edge of the scrolling region. + scrollToLeft: function() { + this.setScrollLeft(0); + }, + //* Ensures scroll position is in bounds. + stabilize: function() { + var s = this.getStrategy(); + if (s.stabilize) { + s.stabilize(); + } + } +}); + +// provide a touch scrolling solution by default when the environment is mobile +if (enyo.Scroller.hasTouchScrolling()) { + enyo.Scroller.prototype.strategyKind = enyo.Scroller.getTouchStrategy(); +} diff --git a/enyo/source/touch/Thumb.css b/enyo/source/touch/Thumb.css new file mode 100644 index 0000000..81e998f --- /dev/null +++ b/enyo/source/touch/Thumb.css @@ -0,0 +1,22 @@ +.enyo-thumb { + position: absolute; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; + background: #333; + border: 1px solid #666; + opacity: 0.75; + z-index: 1; +} + +.enyo-vthumb { + top: 0; + right: 2px; + width: 4px; +} + +.enyo-hthumb { + left: 0; + bottom: 2px; + height: 4px; +} diff --git a/enyo/source/touch/Thumb.js b/enyo/source/touch/Thumb.js new file mode 100644 index 0000000..769919c --- /dev/null +++ b/enyo/source/touch/Thumb.js @@ -0,0 +1,111 @@ +/** +_enyo.ScrollThumb_ is a helper kind used by +enyo.TouchScrollStrategy and +enyo.TranslateScrollStrategy to +display a small visual scroll indicator. + +_enyo.ScrollThumb_ is not typically created in application code. +*/ + +enyo.kind({ + name: "enyo.ScrollThumb", + //* The orientation of the scroll indicator bar; "v" for vertical or "h" for horizontal + axis: "v", + //* @protected + //* Minimum size of the indicator + minSize: 4, + //* Size of the corners of the indicator + cornerSize: 6, + classes: "enyo-thumb", + create: function() { + this.inherited(arguments); + var v = this.axis == "v"; + this.dimension = v ? "height" : "width"; + this.offset = v ? "top" : "left"; + this.translation = v ? "translateY" : "translateX"; + this.positionMethod = v ? "getScrollTop" : "getScrollLeft"; + this.sizeDimension = v ? "clientHeight" : "clientWidth"; + this.addClass("enyo-" + this.axis + "thumb"); + this.transform = enyo.dom.canTransform(); + if (enyo.dom.canAccelerate()) { + enyo.dom.transformValue(this, "translateZ", 0); + } + }, + //* Syncs the scroll indicator bar to the scroller size and position, + //* as determined by the passed-in scroll strategy. + sync: function(inStrategy) { + this.scrollBounds = inStrategy._getScrollBounds(); + this.update(inStrategy); + }, + update: function(inStrategy) { + if (this.showing) { + var d = this.dimension, o = this.offset; + var bd = this.scrollBounds[this.sizeDimension], sbd = this.scrollBounds[d]; + var overs = 0, overp = 0, over = 0; + if (bd >= sbd) { + this.hide(); + return; + } + if (inStrategy.isOverscrolling()) { + over = inStrategy.getOverScrollBounds()["over" + o]; + overs = Math.abs(over); + overp = Math.max(over, 0); + } + var sbo = inStrategy[this.positionMethod]() - over; + // calc size & position + var bdc = bd - this.cornerSize; + var s = Math.floor((bd * bd / sbd) - overs); + s = Math.max(this.minSize, s); + var p = Math.floor((bdc * sbo / sbd) + overp); + p = Math.max(0, Math.min(bdc - this.minSize, p)); + // apply thumb styling + this.needed = s < bd; + if (this.needed && this.hasNode()) { + if (this._pos !== p) { + this._pos = p; + if(!this.transform) { + //adjust top/left for browsers that don't support translations + if(this.axis=="v") { + this.setBounds({top:p + "px"}); + } else { + this.setBounds({left:p + "px"}); + } + } else { + enyo.dom.transformValue(this, this.translation, p + "px"); + } + } + if (this._size !== s) { + this._size = s; + this.node.style[d] = this.domStyles[d] = s + "px"; + } + } else { + this.hide(); + } + } + }, + // implement set because showing is not changed while + // we delayHide but we want to cancel the hide. + setShowing: function(inShowing) { + if (inShowing && inShowing != this.showing) { + if (this.scrollBounds[this.sizeDimension] >= this.scrollBounds[this.dimension]) { + return; + } + } + if (this.hasNode()) { + this.cancelDelayHide(); + } + if (inShowing != this.showing) { + var last = this.showing; + this.showing = inShowing; + this.showingChanged(last); + } + }, + delayHide: function(inDelay) { + if (this.showing) { + enyo.job(this.id + "hide", enyo.bind(this, "hide"), inDelay || 0); + } + }, + cancelDelayHide: function() { + enyo.job.stop(this.id + "hide"); + } +}); diff --git a/enyo/source/touch/TouchScrollStrategy.js b/enyo/source/touch/TouchScrollStrategy.js new file mode 100644 index 0000000..9bbe930 --- /dev/null +++ b/enyo/source/touch/TouchScrollStrategy.js @@ -0,0 +1,429 @@ +/** + _enyo.TouchScrollStrategy_ is a helper kind for implementing a touch-based + scroller. It integrates the scrolling simulation provided by + enyo.ScrollMath into an + enyo.Scroller. + + _enyo.TouchScrollStrategy_ is not typically created in application code. + Instead, it is specified as the value of the `strategyKind` property of an + `enyo.Scroller` or enyo.List, or is used by the + framework implicitly. +*/ +enyo.kind({ + name: "enyo.TouchScrollStrategy", + kind: "ScrollStrategy", + /** + If true (the default), the scroller will overscroll and bounce back at the edges + */ + overscroll: true, + /** + If true (the default), the scroller will not propagate _dragstart_ + events that cause it to start scrolling + */ + preventDragPropagation: true, + published: { + /** + Specifies how to vertically scroll. Acceptable values are: + + * "scroll": Always scroll. + * "auto": Scroll only if the content overflows the scroller. + * "hidden": Never scroll. + * "default": In touch environments, the default vertical scrolling + behavior is to always scroll. If the content does not overflow + the scroller, the scroller will overscroll and snap back. + */ + vertical: "default", + /** + Specifies how to horizontally scroll. Acceptable values are: + + * "scroll": Always scroll. + * "auto": Scroll only if the content overflows the scroller. + * "hidden": Never scroll. + * "default": Same as "auto". + */ + horizontal: "default", + //* Set to true to display a scroll thumb + thumb: true, + /** + Set to true to display a transparent overlay while scrolling. This + can help improve performance of complex, large scroll regions on + some platforms (e.g., Android). + */ + scrim: false, + //* Allow drag events sent when gesture events are happening simultaneously + dragDuringGesture: true + }, + events: { + onShouldDrag: "" + }, + //* @protected + handlers: { + onscroll: "domScroll", + onflick: "flick", + onhold: "hold", + ondragstart: "dragstart", + onShouldDrag: "shouldDrag", + ondrag: "drag", + ondragfinish: "dragfinish", + onmousewheel: "mousewheel" + }, + tools: [ + {kind: "ScrollMath", onScrollStart: "scrollMathStart", onScroll: "scrollMathScroll", onScrollStop: "scrollMathStop"}, + {name: "vthumb", kind: "ScrollThumb", axis: "v", showing: false}, + {name: "hthumb", kind: "ScrollThumb", axis: "h", showing: false} + ], + scrimTools: [{name: "scrim", classes: "enyo-fit", style: "z-index: 1;", showing: false}], + components: [ + {name: "client", classes: "enyo-touch-scroller"} + ], + // flag telling us whether the list is currently reordering + listReordering: false, + create: function() { + this.inherited(arguments); + this.transform = enyo.dom.canTransform(); + if(!this.transform) { + if(this.overscroll) { + //so we can adjust top/left if browser can't handle translations + this.$.client.applyStyle("position", "relative"); + } + } + this.accel = enyo.dom.canAccelerate(); + var containerClasses = "enyo-touch-strategy-container"; + // note: needed for ios to avoid incorrect clipping of thumb + // and need to avoid on Android as it causes problems hiding the thumb + if (enyo.platform.ios && this.accel) { + containerClasses += " enyo-composite"; + } + this.scrimChanged(); + this.container.addClass(containerClasses); + this.translation = this.accel ? "translate3d" : "translate"; + }, + initComponents: function() { + this.createChrome(this.tools); + this.inherited(arguments); + }, + destroy: function() { + this.container.removeClass("enyo-touch-strategy-container"); + this.inherited(arguments); + }, + rendered: function() { + this.inherited(arguments); + enyo.makeBubble(this.$.client, "scroll"); + this.calcBoundaries(); + this.syncScrollMath(); + if (this.thumb) { + this.alertThumbs(); + } + }, + scrimChanged: function() { + if (this.scrim && !this.$.scrim) { + this.makeScrim(); + } + if (!this.scrim && this.$.scrim) { + this.$.scrim.destroy(); + } + }, + makeScrim: function() { + // reset control parent so scrim doesn't go into client. + var cp = this.controlParent; + this.controlParent = null; + this.createChrome(this.scrimTools); + this.controlParent = cp; + var cn = this.container.hasNode(); + // render scrim in container, strategy has no dom. + if (cn) { + this.$.scrim.parentNode = cn; + this.$.scrim.render(); + } + }, + //* Whether or not the scroller is actively moving + isScrolling: function() { + var m = this.$.scrollMath; + return m ? m.isScrolling() : this.scrolling; + }, + //* Whether or not the scroller is in overscrolling + isOverscrolling: function() { + var m = this.$.scrollMath || this; + return (this.overscroll) ? m.isInOverScroll() : false; + }, + domScroll: function() { + if (!this.isScrolling()) { + this.calcBoundaries(); + this.syncScrollMath(); + if (this.thumb) { + this.alertThumbs(); + } + } + }, + horizontalChanged: function() { + this.$.scrollMath.horizontal = (this.horizontal != "hidden"); + }, + verticalChanged: function() { + this.$.scrollMath.vertical = (this.vertical != "hidden"); + }, + maxHeightChanged: function() { + this.$.client.applyStyle("max-height", this.maxHeight); + // note: previously used enyo-fit here but IE would reset scroll position when the scroll thumb + // was hidden; in general IE resets scrollTop when there are 2 abs position siblings, one has + // scrollTop and the other is hidden. + this.$.client.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); + }, + thumbChanged: function() { + this.hideThumbs(); + }, + stop: function() { + if (this.isScrolling()) { + this.$.scrollMath.stop(true); + } + }, + stabilize: function() { + if(this.$.scrollMath) { + this.$.scrollMath.stabilize(); + } + }, + //* Scrolls to specific x/y positions within the scroll area. + scrollTo: function(inX, inY) { + this.stop(); + this.$.scrollMath.scrollTo(inX, inY || inY === 0 ? inY : null); + }, + scrollIntoView: function() { + this.stop(); + this.inherited(arguments); + }, + //* Sets the left scroll position within the scroller. + setScrollLeft: function() { + this.stop(); + this.inherited(arguments); + }, + //* Sets the top scroll position within the scroller. + setScrollTop: function() { + this.stop(); + this.inherited(arguments); + }, + //* Gets the left scroll position within the scroller. + getScrollLeft: function() { + return this.isScrolling() ? this.scrollLeft : this.inherited(arguments); + }, + //* Gets the top scroll position within the scroller. + getScrollTop: function() { + return this.isScrolling() ? this.scrollTop : this.inherited(arguments); + }, + calcScrollNode: function() { + return this.$.client.hasNode(); + }, + calcAutoScrolling: function() { + var v = (this.vertical == "auto"); + var h = (this.horizontal == "auto") || (this.horizontal == "default"); + if ((v || h) && this.scrollNode) { + var b = this.getScrollBounds(); + if (v) { + this.$.scrollMath.vertical = b.height > b.clientHeight; + } + if (h) { + this.$.scrollMath.horizontal = b.width > b.clientWidth; + } + } + }, + shouldDrag: function(inSender, e) { + this.calcAutoScrolling(); + var requestV = e.vertical; + var canH = this.$.scrollMath.horizontal && !requestV; + var canV = this.$.scrollMath.vertical && requestV; + var down = e.dy < 0, right = e.dx < 0; + var oobV = (!down && this.startEdges.top || down && this.startEdges.bottom); + var oobH = (!right && this.startEdges.left || right && this.startEdges.right); + // we would scroll if not at a boundary + if (!e.boundaryDragger && (canH || canV)) { + e.boundaryDragger = this; + } + // include boundary exclusion + if ((!oobV && canV) || (!oobH && canH)) { + e.dragger = this; + return true; + } + }, + flick: function(inSender, e) { + var onAxis = Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.$.scrollMath.horizontal : this.$.scrollMath.vertical; + if (onAxis && this.dragging) { + this.$.scrollMath.flick(e); + return this.preventDragPropagation; + } + }, + hold: function(inSender, e) { + if (this.isScrolling() && !this.isOverscrolling()) { + var m = this.$.scrollMath || this; + m.stop(e); + return true; + } + }, + move: function(inSender, inEvent) { + }, + // Special synthetic DOM events served up by the Gesture system + dragstart: function(inSender, inEvent) { + // Ignore drags sent from multi-touch events + if(!this.dragDuringGesture && inEvent.srcEvent.touches && inEvent.srcEvent.touches.length > 1) { + return true; + } + // note: allow drags to propagate to parent scrollers via data returned in the shouldDrag event. + this.doShouldDrag(inEvent); + this.dragging = (inEvent.dragger == this || (!inEvent.dragger && inEvent.boundaryDragger == this)); + if (this.dragging) { + inEvent.preventDefault(); + // note: needed because show/hide changes + // the position so sync'ing is required when + // dragging begins (needed because show/hide does not trigger onscroll) + this.syncScrollMath(); + this.$.scrollMath.startDrag(inEvent); + if (this.preventDragPropagation) { + return true; + } + } + }, + drag: function(inSender, inEvent) { + // if the list is doing a reorder, don't scroll + if(this.listReordering) { + return false; + } + if (this.dragging) { + inEvent.preventDefault(); + this.$.scrollMath.drag(inEvent); + if (this.scrim) { + this.$.scrim.show(); + } + } + }, + dragfinish: function(inSender, inEvent) { + if (this.dragging) { + inEvent.preventTap(); + this.$.scrollMath.dragFinish(); + this.dragging = false; + if (this.scrim) { + this.$.scrim.hide(); + } + } + }, + mousewheel: function(inSender, e) { + if (!this.dragging) { + this.calcBoundaries(); + this.syncScrollMath(); + this.stabilize(); + if (this.$.scrollMath.mousewheel(e)) { + e.preventDefault(); + return true; + } + } + }, + scrollMathStart: function(inSender) { + if (this.scrollNode) { + this.calcBoundaries(); + if (this.thumb) { + this.showThumbs(); + } + } + }, + scrollMathScroll: function(inSender) { + if(!this.overscroll) { + //don't overscroll past edges + this.effectScroll(-Math.min(inSender.leftBoundary, Math.max(inSender.rightBoundary, inSender.x)), + -Math.min(inSender.topBoundary, Math.max(inSender.bottomBoundary, inSender.y))); + } else { + this.effectScroll(-inSender.x, -inSender.y); + } + if (this.thumb) { + this.updateThumbs(); + } + }, + scrollMathStop: function(inSender) { + this.effectScrollStop(); + if (this.thumb) { + this.delayHideThumbs(100); + } + }, + calcBoundaries: function() { + var s = this.$.scrollMath || this, b = this._getScrollBounds(); + s.bottomBoundary = b.clientHeight - b.height; + s.rightBoundary = b.clientWidth - b.width; + }, + syncScrollMath: function() { + var m = this.$.scrollMath; + if(m) { + m.setScrollX(-this.getScrollLeft()); + m.setScrollY(-this.getScrollTop()); + } + }, + effectScroll: function(inX, inY) { + if (this.scrollNode) { + this.scrollLeft = this.scrollNode.scrollLeft = inX; + this.scrollTop = this.scrollNode.scrollTop = inY; + this.effectOverscroll(Math.round(inX), Math.round(inY)); + } + }, + effectScrollStop: function() { + this.effectOverscroll(null, null); + }, + effectOverscroll: function(inX, inY) { + var n = this.scrollNode; + var x = "0", y = "0", z = this.accel ? ",0" : ""; + if (inY !== null && Math.abs(inY - n.scrollTop) > 1) { + y = (n.scrollTop - inY); + } + if (inX !== null && Math.abs(inX - n.scrollLeft) > 1) { + x = (n.scrollLeft - inX); + } + if(!this.transform) { + //adjust top/left if browser can't handle translations + this.$.client.setBounds({left:x + "px", top:y + "px"}); + } else { + enyo.dom.transformValue(this.$.client, this.translation, x + "px, " + y + "px" + z); + } + }, + //* Returns the values of _overleft_ and _overtop_, if any. + getOverScrollBounds: function() { + var m = this.$.scrollMath || this; + return { + overleft: Math.min(m.leftBoundary - m.x, 0) || Math.max(m.rightBoundary - m.x, 0), + overtop: Math.min(m.topBoundary - m.y, 0) || Math.max(m.bottomBoundary - m.y, 0) + }; + }, + _getScrollBounds: function() { + var r = this.inherited(arguments); + enyo.mixin(r, this.getOverScrollBounds()); + return r; + }, + getScrollBounds: function() { + this.stop(); + return this.inherited(arguments); + }, + // Thumb processing + alertThumbs: function() { + this.showThumbs(); + this.delayHideThumbs(500); + }, + //* Syncs the vertical and horizontal scroll indicators. + syncThumbs: function() { + this.$.vthumb.sync(this); + this.$.hthumb.sync(this); + }, + updateThumbs: function() { + this.$.vthumb.update(this); + this.$.hthumb.update(this); + }, + //* Syncs and shows both the vertical and horizontal scroll indicators. + showThumbs: function() { + this.syncThumbs(); + if (this.horizontal != "hidden") + this.$.hthumb.show(); + if (this.vertical != "hidden") + this.$.vthumb.show(); + }, + //* Hides the vertical and horizontal scroll indicators. + hideThumbs: function() { + this.$.vthumb.hide(); + this.$.hthumb.hide(); + }, + //* Hides the vertical and horizontal scroll indicators asynchronously. + delayHideThumbs: function(inDelay) { + this.$.vthumb.delayHide(inDelay); + this.$.hthumb.delayHide(inDelay); + } +}); diff --git a/enyo/source/touch/TransitionScrollStrategy.js b/enyo/source/touch/TransitionScrollStrategy.js new file mode 100644 index 0000000..92e56a6 --- /dev/null +++ b/enyo/source/touch/TransitionScrollStrategy.js @@ -0,0 +1,616 @@ +/** + _enyo.TransitionScrollStrategy_ is a helper kind that extends + enyo.TouchScrollStrategy, optimizing + it for scrolling environments in which effecting scroll changes with + transforms using CSS transitions is fastest. + + _enyo.TransitionScrollStrategy_ is not typically created in application code. + Instead, it is specified as the value of the `strategyKind` property of an + `enyo.Scroller` or enyo.List, or is used by the + framework implicitly. +*/ +enyo.kind({ + name: "enyo.TransitionScrollStrategy", + kind: "enyo.TouchScrollStrategy", + //* @protected + components: [ + {name: "clientContainer", classes: "enyo-touch-scroller", components: [ + {name: "client"} + ]} + ], + events: { + onScrollStart: "", + onScroll: "", + onScrollStop: "" + }, + handlers: { + ondown: "down", + ondragfinish: "dragfinish", + onwebkitTransitionEnd: "transitionComplete" + }, + //* No scrollMath tool for this strategy + tools: [ + {name: "vthumb", kind: "ScrollThumb", axis: "v", showing: true}, + {name: "hthumb", kind: "ScrollThumb", axis: "h", showing: false} + ], + //* Scalar applied to 'flick' event velocity + kFlickScalar: 600, + //* Top snap boundary, generally 0 + topBoundary: 0, + //* Right snap boundary, generally (viewport width - content width) + rightBoundary: 0, + //* Bottom snap boundary, generally (viewport height - content height) + bottomBoundary: 0, + //* Left snap boundary, generally 0 + leftBoundary: 0, + //* Flag to specify whether scrolling is in progress + scrolling: false, + //* Event listener for webkit transition completion + listener: null, + //* X Distance to scroll into overscroll space before bouncing back + boundaryX:0, + //* Y Distance to scroll into overscroll space before bouncing back + boundaryY:0, + //* Timeout used to stop scrolling on mousedown + stopTimeout: null, + //* MS delay used to stop scrolling on mousedown + stopTimeoutMS: 80, + //* Interval used to update scroll values and bubble scroll events during scroll animation + scrollInterval: null, + //* MS delay used to update scroll values and bubble scroll events during scroll animation + scrollIntervalMS: 50, + //* Transition animations + transitions: { + //* None - used for dragging, etc. + none : "", + //* Scroll - basic scrolling behavior + scroll : "3.8s cubic-bezier(.19,1,.28,1.0) 0s", + //* Bounce - overscroll bounceback behavior + bounce : "0.5s cubic-bezier(0.06,.5,.5,.94) 0s" + }, + + //* @public + + //* Sets the left scroll position within the scroller. + setScrollLeft: function(inLeft) { + var prevLeft = this.scrollLeft; + this.stop(); + this.scrollLeft = inLeft; + if(this.isInLeftOverScroll() || this.isInRightOverScroll()) { + this.scrollLeft = prevLeft; + } + this.effectScroll(); + }, + //* Sets the top scroll position within the scroller. + setScrollTop: function(inTop) { + var prevTop = this.scrollTop; + this.stop(); + this.scrollTop = inTop; + if(this.isInTopOverScroll() || this.isInBottomOverScroll()) { + this.scrollTop = prevTop; + } + this.effectScroll(); + }, + setScrollX: function(inLeft) { + this.scrollLeft = -1*inLeft; + }, + setScrollY: function(inTop) { + this.scrollTop = -1*inTop; + }, + + //* Gets the left scroll position within the scroller. + getScrollLeft: function() { + return this.scrollLeft; + }, + //* Gets the top scroll position within the scroller. + getScrollTop: function() { + return this.scrollTop; + }, + + //* @protected + + // apply initial transform so we're always composited + create: function() { + this.inherited(arguments); + enyo.dom.transformValue(this.$.client, this.translation, "0,0,0"); + }, + destroy: function() { + this.clearCSSTransitionInterval(); + this.inherited(arguments); + }, + getScrollSize: function() { + var n = this.$.client.hasNode(); + return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; + }, + horizontalChanged: function() { + if(this.horizontal == "hidden") { + this.scrollHorizontal = false; + } + }, + verticalChanged: function() { + if(this.vertical == "hidden") { + this.scrollVertical = false; + } + }, + calcScrollNode: function() { + return this.$.clientContainer.hasNode(); + }, + calcBoundaries: function() { + var b = this._getScrollBounds(); + this.bottomBoundary = b.clientHeight - b.height; + this.rightBoundary = b.clientWidth - b.width; + }, + maxHeightChanged: function() { + // content should cover scroller at a minimum if there's no max-height. + this.$.client.applyStyle("min-height", this.maxHeight ? null : "100%"); + this.$.client.applyStyle("max-height", this.maxHeight); + this.$.clientContainer.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); + }, + calcAutoScrolling: function() { + var b = this.getScrollBounds(); + if(this.vertical) { + this.scrollVertical = b.height > b.clientHeight; + } + if(this.horizontal) { + this.scrollHorizontal = b.width > b.clientWidth; + } + }, + isInOverScroll: function() { + return (this.isInTopOverScroll() || this.isInBottomOverScroll() || this.isInLeftOverScroll() || this.isInRightOverScroll()); + }, + isInLeftOverScroll: function() { + return (this.getScrollLeft() < this.leftBoundary); + }, + isInRightOverScroll: function() { + if(this.getScrollLeft <= 0) { + return false; + } else { + return (this.getScrollLeft()*-1 < this.rightBoundary); + } + }, + isInTopOverScroll: function() { + return (this.getScrollTop() < this.topBoundary); + }, + isInBottomOverScroll: function() { + if(this.getScrollTop() <= 0) { + return false; + } else { + return (this.getScrollTop()*-1 < this.bottomBoundary); + } + }, + calcStartInfo: function() { + var sb = this.getScrollBounds(), y = this.getScrollTop(), x = this.getScrollLeft(); + this.startEdges = { + top: y === 0, + bottom: y === sb.maxTop, + left: x === 0, + right: x === sb.maxLeft + }; + }, + mousewheel: function(inSender, e) { + if (!this.dragging) { + this.calcBoundaries(); + this.syncScrollMath(); + this.stabilize(); + var dy = this.vertical ? e.wheelDeltaY || e.wheelDelta : 0; + var y = parseFloat(this.getScrollTop()) + -1*parseFloat(dy); + y = (y*-1 < this.bottomBoundary) ? -1*this.bottomBoundary : (y < this.topBoundary) ? this.topBoundary : y; + this.setScrollTop(y); + this.doScroll(); + e.preventDefault(); + return true; + } + }, + // Update thumbs, recalculate boundaries, and bubble scroll event + scroll: function(inSender, inEvent) { + if(this.thumb) { + this.updateThumbs(); + } + this.calcBoundaries(); + this.doScroll(); + }, + // Scroll to current x,y coordinates and bubble scrollstart event + start: function() { + this.startScrolling(); + this.doScrollStart(); + }, + // If scrolling, stop. Hide thumbs and bubble scrollstop event. + stop: function() { + if(this.isScrolling()) { + this.stopScrolling(); + } + if (this.thumb) { + this.delayHideThumbs(100); + } + this.doScrollStop(); + }, + + // Set scroll x value to the current computed style + updateX: function() { + var x = window.getComputedStyle(this.$.client.node,null).getPropertyValue(enyo.dom.getCssTransformProp()).split('(')[1]; + x = (x == undefined) ? 0 : x.split(')')[0].split(',')[4]; + if(-1*parseFloat(x) === this.scrollLeft) { + return false; + } + this.scrollLeft = -1*parseFloat(x); + return true; + }, + // Set scroll y value to the current computed style + updateY: function() { + var y = window.getComputedStyle(this.$.client.node,null).getPropertyValue(enyo.dom.getCssTransformProp()).split('(')[1]; + y = (y == undefined) ? 0 : y.split(')')[0].split(',')[5]; + if(-1*parseFloat(y) === this.scrollTop) { + return false; + } + this.scrollTop = -1*parseFloat(y); + return true; + }, + // Apply transform to scroll the scroller + effectScroll: function() { + var o = (-1*this.scrollLeft) + "px, " + (-1*this.scrollTop) + "px" + (this.accel ? ", 0" : ""); + enyo.dom.transformValue(this.$.client, this.translation, o); + }, + // On touch, stop transition by setting transform values to current computed style, and + // changing transition time to 0s. TODO + down: function(inSender, inEvent) { + var _this = this; + if (this.isScrolling() && !this.isOverscrolling()) { + this.stopTimeout = setTimeout(function() { _this.stop(); }, this.stopTimeoutMS); + return true; + } + }, + // Special synthetic DOM events served up by the Gesture system + dragstart: function(inSender, inEvent) { + if(this.stopTimeout) { + clearTimeout(this.stopTimeout); + } + // Ignore drags sent from multi-touch events + if(!this.dragDuringGesture && inEvent.srcEvent.touches && inEvent.srcEvent.touches.length > 1) { + return true; + } + this.shouldDrag(inEvent); + this.dragging = (inEvent.dragger == this || (!inEvent.dragger && inEvent.boundaryDragger == this)); + if (this.dragging) { + if(this.isScrolling()) { + this.stopScrolling(); + } + if(this.thumb) { + this.showThumbs(); + } + inEvent.preventDefault(); + this.prevY = inEvent.pageY; + this.prevX = inEvent.pageX; + if (this.preventDragPropagation) { + return true; + } + } + }, + // Determine if we should allow dragging + shouldDrag: function(e) { + this.calcStartInfo(); + this.calcBoundaries(); + this.calcAutoScrolling(); + if(!this.scrollHorizontal) { + return this.shouldDragVertical(e); + } else { + if(!this.scrollVertical) { + return this.shouldDragHorizontal(e); + } else { + return (this.shouldDragVertical(e) || this.shouldDragHorizontal(e)); + } + } + }, + shouldDragVertical: function(e) { + var canV = this.canDragVertical(e); + var oobV = this.oobVertical(e); + // scroll if not at a boundary + if (!e.boundaryDragger && canV) { + e.boundaryDragger = this; + } + // include boundary exclusion + if (!oobV && canV) { + e.dragger = this; + return true; + } + }, + shouldDragHorizontal: function(e) { + var canH = this.canDragHorizontal(e); + var oobH = this.oobHorizontal(e); + // scroll if not at a boundary + if (!e.boundaryDragger && canH) { + e.boundaryDragger = this; + } + // include boundary exclusion + if (!oobH && canH) { + e.dragger = this; + return true; + } + }, + canDragVertical: function(e) { + return (this.scrollVertical && e.vertical); + }, + canDragHorizontal: function(e) { + return (this.scrollHorizontal && !e.vertical); + }, + oobVertical: function(e) { + var down = e.dy < 0; + return (!down && this.startEdges.top || down && this.startEdges.bottom); + }, + oobHorizontal: function(e) { + var right = e.dx < 0; + return (!right && this.startEdges.left || right && this.startEdges.right); + }, + // Move scroller based on user's dragging + drag: function(inSender, e) { + // if the list is doing a reorder, don't scroll + if(this.listReordering) { + return false; + } + // if shouldDrag() set this.dragging to true + if(this.dragging) { + e.preventDefault(); + // calculate new scroll values + this.scrollLeft = this.scrollHorizontal ? + this.calculateDragDistance(parseInt(this.getScrollLeft(), 10), (-1*(e.pageX-this.prevX)), this.leftBoundary, this.rightBoundary) : + this.getScrollLeft(); + this.scrollTop = this.scrollVertical ? + this.calculateDragDistance(this.getScrollTop(), (-1*(e.pageY-this.prevY)), this.topBoundary, this.bottomBoundary) : + this.getScrollTop(); + // apply new scroll values + this.effectScroll(); + this.scroll(); + // save values for next drag + this.prevY = e.pageY; + this.prevX = e.pageX; + this.resetBoundaryX(); + this.resetBoundaryY(); + } + }, + //* Figure how far the drag should go based on pointer movement (delta) + calculateDragDistance: function(currentPosition, delta, aBoundary, bBoundary) { + var newPosition = currentPosition + delta; + return this.overscrollDragDamping(currentPosition, newPosition,delta,aBoundary,bBoundary); + }, + //* Provides resistance against dragging into overscroll + overscrollDragDamping: function(currentPosition, newPosition, delta, aBoundary, bBoundary) { + if(newPosition < aBoundary || newPosition*-1 < bBoundary) { + delta /= 2; + newPosition = currentPosition + delta; + } + return newPosition; + }, + resetBoundaryX: function() { + this.boundaryX = 0; + }, + resetBoundaryY: function() { + this.boundaryY = 0; + }, + // When user releases the drag, set this.dragging to false, bounce overflow back, and hide scrim. + dragfinish: function(inSender, inEvent) { + if (this.dragging) { + inEvent.preventTap(); + this.dragging = false; + if(!this.isScrolling()) { + this.correctOverflow(); + } + if (this.scrim) { + this.$.scrim.hide(); + } + } + }, + // Bounce back from overscroll region + correctOverflow: function() { + if(this.isInOverScroll()) { + var x = (this.scrollHorizontal) ? this.correctOverflowX() : false; + var y = (this.scrollVertical) ? this.correctOverflowY() : false; + if(x !== false && y !== false) { + this.scrollLeft = (x !== false) ? x : this.getScrollLeft(); + this.scrollTop = (y !== false) ? y : this.getScrollTop(); + this.startOverflowScrolling(); + } else if(x !== false) { + this.scrollLeft = x; + this.scrollTop = this.targetScrollTop || this.scrollTop; + this.targetScrollLeft = this.getScrollLeft(); + if(!this.vertical) { + this.startOverflowScrolling(); + } else { + this.startScrolling(); + } + } else if(y !== false) { + this.scrollTop = y; + this.scrollLeft = this.targetScrollLeft || this.scrollLeft; + this.targetScrollTop = this.getScrollTop(); + if(!this.scrollHorizontal) { + this.startOverflowScrolling(); + } else { + this.startScrolling(); + } + } + } + }, + // Determine if we're overscrolled on the x axis and if so return proper edge value + correctOverflowX: function() { + if(this.isInLeftOverScroll()) { + if(this.beyondBoundary(this.getScrollLeft(), this.leftBoundary, this.boundaryX)) { + return this.leftBoundary; + } + } else if(this.isInRightOverScroll()) { + if(this.beyondBoundary(this.getScrollLeft(), this.rightBoundary, this.boundaryX)) { + return -1*this.rightBoundary; + } + } + return false; + }, + // Determine if we're overscrolled on the y axis and if so return proper edge value + correctOverflowY: function() { + if(this.isInTopOverScroll()) { + if(this.beyondBoundary(this.getScrollTop(), this.topBoundary, this.boundaryY)) { + return this.topBoundary; + } + } else if(this.isInBottomOverScroll()) { + if(this.beyondBoundary(this.getScrollTop(), this.bottomBoundary, this.boundaryY)) { + return -1*this.bottomBoundary; + } + } + return false; + }, + // If we've crossed the determined delta, bounce back + beyondBoundary: function(current,boundary,max) { + return (Math.abs(Math.abs(boundary) - Math.abs(current)) > Math.abs(max)); + }, + // When user flicks/throws scroller, figure the distance to be travelled and whether we will end up + // in the overscroll region. + flick: function(inSender, e) { + if(this.dragging && this.flickOnEnabledAxis(e)) { + this.scrollLeft = this.scrollHorizontal ? this.calculateFlickDistance(this.scrollLeft, -1*e.xVelocity) : this.getScrollLeft(); + this.scrollTop = this.scrollVertical ? this.calculateFlickDistance(this.scrollTop, -1*e.yVelocity) : this.getScrollTop(); + this.targetScrollLeft = this.scrollLeft; + this.targetScrollTop = this.scrollTop; + this.boundaryX = null; + this.boundaryY = null; + // if flick will put the x axis into overscroll, figure where we should bounce back (boundary) + if(this.isInLeftOverScroll()) { + this.boundaryX = this.figureBoundary(this.getScrollLeft()); + } else if(this.isInRightOverScroll()) { + this.boundaryX = this.figureBoundary(-1*this.bottomBoundary - this.getScrollLeft()); + } + // if flick will put the y axis into overscroll, figure where we should bounce back (boundary) + if(this.isInTopOverScroll()) { + this.boundaryY = this.figureBoundary(this.getScrollTop()); + } else if(this.isInBottomOverScroll()) { + this.boundaryY = this.figureBoundary(-1*this.bottomBoundary - this.getScrollTop()); + } + // kickoff scrolling animation + this.startScrolling(); + return this.preventDragPropagation; + } + }, + flickOnEnabledAxis: function(e) { + return Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.scrollHorizontal : this.scrollVertical; + }, + calculateFlickDistance: function(currentPosition, flickVelocity) { + return (currentPosition + (flickVelocity * this.kFlickScalar)); + }, + // Apply the 'scroll' transition, apply new transform based on x and y, and begin + // this.scrollInterval to update the scrollTop/Left values while scrolling + startScrolling: function() { + this.applyTransition("scroll"); + this.effectScroll(); + this.setCSSTransitionInterval(); + this.scrolling = true; + }, + // Apply the 'bounce' transition, apply new transform based on x and y, and begin + // this.scrollInterval to update the scrollTop/Left values while scrolling + startOverflowScrolling: function() { + this.applyTransition("bounce"); + this.effectScroll(); + this.setOverflowTransitionInterval(); + this.scrolling = true; + }, + // Apply the given transition to this.$.client + applyTransition: function(which) { + var transform = this.translation+": "+this.transitions[which]; + this.$.client.applyStyle("-webkit-transition",this.transitions[which]); + }, + // Turn off CSS transition and clear this.scrollInterval + stopScrolling: function() { + this.resetCSSTranslationVals(); + this.clearCSSTransitionInterval(); + this.scrolling = false; + }, + // Create an interval to: update the x/y values while scrolling is happening, check for + // crossing into the overflow region, and bubble a scroll event + setCSSTransitionInterval: function() { + this.clearCSSTransitionInterval(); + this.scrollInterval = setInterval(enyo.bind(this, function() { + this.updateScrollPosition(); + this.correctOverflow(); + }), this.scrollIntervalMS); + }, + // Create an interval to: update the x/y values while scrolling is happening, and bubble + // a scroll event (don't check for crossing into overflow since we're there already) + setOverflowTransitionInterval: function() { + this.clearCSSTransitionInterval(); + this.scrollInterval = setInterval(enyo.bind(this, function() { + this.updateScrollPosition(); + }), this.scrollIntervalMS); + }, + // Save current x/y position and bubble scroll event + updateScrollPosition: function() { + var yChanged = this.updateY(); + var xChanged = this.updateX(); + this.scroll(); + if(!yChanged && !xChanged) { + this.stop(); + } + }, + // Clear this.scrollInterval + clearCSSTransitionInterval: function() { + if(this.scrollInterval) { + clearInterval(this.scrollInterval); + this.scrollInterval = null; + } + }, + // Set scroller translation to current position and turn transition off. This effectively + // stops scrolling + resetCSSTranslationVals: function() { + var prop = enyo.dom.getCssTransformProp(); + var transformStyle = window.getComputedStyle(this.$.client.node,null).getPropertyValue(prop).split('(')[1].split(')')[0].split(','); + this.applyTransition("none"); + this.scrollLeft = -1*transformStyle[4]; + this.scrollTop = -1*transformStyle[5]; + this.effectScroll(); + }, + // Figure how far into the overscroll region we should go before bouncing back + figureBoundary: function(target) { + var absTarget = Math.abs(target); + var retVal = absTarget - absTarget/Math.pow(absTarget,0.02); + retVal = target < 0 ? -1*retVal : retVal; + return retVal; + }, + // When transition animation is complete, check if we need to bounce back from overscroll + // region. If not, stop. + transitionComplete: function(inSender, inEvent) { + // Only process transition complete if sent from this container + if(inEvent.originator !== this.$.client) { + return; + } + + var posChanged = false; + + if(this.isInTopOverScroll()) { + posChanged = true; + this.scrollTop = this.topBoundary; + } else if (this.isInBottomOverScroll()) { + posChanged = true; + this.scrollTop = -1*this.bottomBoundary; + } + + if(this.isInLeftOverScroll()) { + posChanged = true; + this.scrollLeft = this.leftBoundary; + } else if (this.isInRightOverScroll()) { + posChanged = true; + this.scrollLeft = -1*this.rightBoundary; + } + + if(posChanged) { + this.startOverflowScrolling(); + } else { + this.stop(); + } + }, + //* Scroll to the specified x and y coordinates + scrollTo: function(inX, inY) { + this.setScrollTop(inY); + this.setScrollLeft(inX); + this.start(); + }, + //* Returns the values of _overleft_ and _overtop_, if any. + getOverScrollBounds: function() { + return { + overleft: Math.min(this.leftBoundary + this.scrollLeft, 0) || Math.max(this.rightBoundary + this.scrollLeft, 0), + overtop: Math.min(this.topBoundary + this.scrollTop, 0) || Math.max(this.bottomBoundary + this.scrollTop, 0) + }; + } +}); diff --git a/enyo/source/touch/TranslateScrollStrategy.js b/enyo/source/touch/TranslateScrollStrategy.js new file mode 100644 index 0000000..4d08366 --- /dev/null +++ b/enyo/source/touch/TranslateScrollStrategy.js @@ -0,0 +1,157 @@ +/** + _enyo.TranslateScrollStrategy_ is a helper kind that extends + enyo.TouchScrollStrategy, optimizing + it for scrolling environments in which effecting scroll changes with + transforms is fastest. + + _enyo.TranslateScrollStrategy_ is not typically created in application code. + Instead, it is specified as the value of the `strategyKind` property of an + `enyo.Scroller` or enyo.List, or is used by the + framework implicitly. +*/ +enyo.kind({ + name: "enyo.TranslateScrollStrategy", + kind: "TouchScrollStrategy", + //* Set to true to optimize the strategy to only use translation to scroll; this increases fluidity of + //* scrolling animation. It should not be used when the scroller contains controls that require keyboard + //* input. This is because when _translateOptimized_ is true, it is possible to position inputs such that + //* they will not become visibile when focused. + translateOptimized: false, + //* @protected + components: [ + {name: "clientContainer", classes: "enyo-touch-scroller", components: [ + {name: "client"} + ]} + ], + rendered: function() { + this.inherited(arguments); + enyo.makeBubble(this.$.clientContainer, "scroll"); + }, + getScrollSize: function() { + var n = this.$.client.hasNode(); + return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; + }, + create: function() { + this.inherited(arguments); + // apply initial transform so we're always composited + enyo.dom.transformValue(this.$.client, this.translation, "0,0,0"); + }, + calcScrollNode: function() { + return this.$.clientContainer.hasNode(); + }, + maxHeightChanged: function() { + // content should cover scroller at a minimum if there's no max-height. + this.$.client.applyStyle("min-height", this.maxHeight ? null : "100%"); + this.$.client.applyStyle("max-height", this.maxHeight); + this.$.clientContainer.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); + }, + shouldDrag: function(inSender, inEvent) { + // stop and update drag info before checking drag status + this.stop(); + this.calcStartInfo(); + return this.inherited(arguments); + }, + syncScrollMath: function() { + if (!this.translateOptimized) { + this.inherited(arguments); + } + }, + //* @public + //* Sets the left scroll position within the scroller. + setScrollLeft: function(inLeft) { + this.stop(); + if (this.translateOptimized) { + var m = this.$.scrollMath; + m.setScrollX(-inLeft); + m.stabilize(); + } else { + this.inherited(arguments); + } + }, + //* Sets the top scroll position within the scroller. + setScrollTop: function(inTop) { + this.stop(); + if (this.translateOptimized) { + var m = this.$.scrollMath; + m.setScrollY(-inTop); + m.stabilize(); + } else { + this.inherited(arguments); + } + }, + //* Gets the left scroll position within the scroller. + getScrollLeft: function() { + return this.translateOptimized ? this.scrollLeft: this.inherited(arguments); + }, + //* Gets the top scroll position within the scroller. + getScrollTop: function() { + return this.translateOptimized ? this.scrollTop : this.inherited(arguments); + }, + //* @protected + scrollMathStart: function(inSender) { + this.inherited(arguments); + this.scrollStarting = true; + this.startX = 0; + this.startY = 0; + if (!this.translateOptimized && this.scrollNode) { + this.startX = this.getScrollLeft(); + this.startY = this.getScrollTop(); + } + }, + scrollMathScroll: function(inSender) { + if(!this.overscroll) { //don't overscroll past edges + this.scrollLeft = -Math.min(inSender.leftBoundary, Math.max(inSender.rightBoundary, inSender.x)); + this.scrollTop = -Math.min(inSender.topBoundary, Math.max(inSender.bottomBoundary, inSender.y)); + } else { + this.scrollLeft = -inSender.x; + this.scrollTop = -inSender.y; + } + if (this.isScrolling()) { + if (this.$.scrollMath.isScrolling()) { + this.effectScroll(this.startX - this.scrollLeft, this.startY - this.scrollTop); + } + if (this.thumb) { + this.updateThumbs(); + } + } + }, + // While moving, scroller uses translate. + effectScroll: function(inX, inY) { + var o = inX + "px, " + inY + "px" + (this.accel ? ",0" : ""); + enyo.dom.transformValue(this.$.client, this.translation, o); + }, + // When stopped, we use scrollLeft/Top (makes cursor positioning automagic). + effectScrollStop: function() { + if (!this.translateOptimized) { + var t = "0,0" + (this.accel ? ",0" : ""); + // FIXME: normally translate3d changes not effect scrollHeight; however + // there appear to be some dom changes (e.g. showing a node inside the scroller, + // which do cause the scrollHeight to be changed from the translate3d. + // In this case setting the translate3d back to 0 does not restore scrollHeight. + // This causes a problem because setting scrollTop can produced an unexpected result if + // scrollHeight is less than expected. + // We detect this fault by validating scroll bounds and (1) un-apply the translate3d, + // (2) update scrollTop/Left, and (3) re-apply a 0,0,0 translate3d to ensure compositing. + // Luckily this corrects the problem (which appears to be a webkit bug). Note that + // it's important to maintain a composited state (translate3d 0,0,0) or Android 4 is + // slow to start scrolling. + var m = this.$.scrollMath, sb = this._getScrollBounds(); + var needsBoundsFix = Boolean((sb.maxTop + m.bottomBoundary) || (sb.maxLeft + m.rightBoundary)); + enyo.dom.transformValue(this.$.client, this.translation, needsBoundsFix ? null : t); + // note: this asynchronously triggers dom scroll event + this.setScrollLeft(this.scrollLeft); + this.setScrollTop(this.scrollTop); + if (needsBoundsFix) { + enyo.dom.transformValue(this.$.client, this.translation, t); + } + } + }, + // FIXME: we can fix scrolling artifacts BUGS on Android 4.04 with this heinous incantation. + twiddle: function() { + if (this.translateOptimized && this.scrollNode) { // this.scrollNode is not always defined and makes Motorola XOOM crash + this.scrollNode.scrollTop = 1; + this.scrollNode.scrollTop = 0; + } + }, + down: enyo.nop +}); \ No newline at end of file diff --git a/enyo/source/touch/gesture.js b/enyo/source/touch/gesture.js new file mode 100644 index 0000000..2b42cc5 --- /dev/null +++ b/enyo/source/touch/gesture.js @@ -0,0 +1,130 @@ +/** + Gesture events: emulates iOS gesture events on non iOS devices + Event Contents + - pageX / pageY: center point between fingers + - rotation: degrees of rotation from beginning of gesture + - scale: % change of distance between fingers +*/ +//* @protected +(function() { + if (!enyo.platform.gesture && enyo.platform.touch) { + enyo.dispatcher.features.push(function(e) { + if (handlers[e.type]) { + touchGestures[e.type](e); + } + }); + } + var handlers = { + touchstart: true, + touchmove: true, + touchend: true + }; + var touchGestures = { + orderedTouches: [], + gesture: null, + touchstart: function(inEvent) { + // some devices can send multiple changed touches on start and end + enyo.forEach(inEvent.changedTouches, function(t) { + var id = t.identifier; + // some devices can send multiple touchstarts + if (enyo.indexOf(id, this.orderedTouches) < 0) { + this.orderedTouches.push(id); + } + }, this); + if (inEvent.touches.length >= 2 && !this.gesture) { + var p = this.gesturePositions(inEvent); + this.gesture = this.gestureVector(p); + this.gesture.angle = this.gestureAngle(p); + this.gesture.scale = 1; + this.gesture.rotation = 0; + var g = this.makeGesture("gesturestart", inEvent, {vector: this.gesture, scale: 1, rotation: 0}); + enyo.dispatch(g); + } + }, + touchend: function(inEvent) { + // some devices can send multiple changed touches on start and end + enyo.forEach(inEvent.changedTouches, function(t) { + enyo.remove(t.identifier, this.orderedTouches); + }, this); + if (inEvent.touches.length <= 1 && this.gesture) { + var t = inEvent.touches[0] || inEvent.changedTouches[inEvent.changedTouches.length - 1]; + // gesture end sends last rotation and scale, with the x/y of the last finger + enyo.dispatch(this.makeGesture("gestureend", inEvent, {vector: {xcenter: t.pageX, ycenter: t.pageY}, scale: this.gesture.scale, rotation: this.gesture.rotation})); + this.gesture = null; + } + }, + touchmove: function(inEvent) { + if (this.gesture) { + var g = this.makeGesture("gesturechange", inEvent); + this.gesture.scale = g.scale; + this.gesture.rotation = g.rotation; + enyo.dispatch(g); + } + }, + findIdentifiedTouch: function(inTouches, inId) { + for (var i = 0, t; (t = inTouches[i]); i++) { + if (t.identifier === inId) { + return t; + } + } + }, + gesturePositions: function(inEvent) { + var first = this.findIdentifiedTouch(inEvent.touches, this.orderedTouches[0]); + var last = this.findIdentifiedTouch(inEvent.touches, this.orderedTouches[this.orderedTouches.length - 1]); + var fx = first.pageX, lx = last.pageX, fy = first.pageY, ly = last.pageY; + // center the first touch as 0,0 + var x = lx - fx, y = ly - fy; + var h = Math.sqrt(x*x + y*y); + return {x: x, y: y, h: h, fx: fx, lx: lx, fy: fy, ly: ly}; + }, + // find rotation angle + gestureAngle: function(inPositions) { + var p = inPositions; + // yay math!, rad -> deg + var a = Math.asin(p.y / p.h) * (180 / Math.PI); + // fix for range limits of asin (-90 to 90) + // Quadrants II and III + if (p.x < 0) { + a = 180 - a; + } + // Quadrant IV + if (p.x > 0 && p.y < 0) { + a += 360; + } + return a; + }, + // find bounding box + gestureVector: function(inPositions) { + // the least recent touch and the most recent touch determine the bounding box of the gesture event + var p = inPositions; + // center the first touch as 0,0 + return { + magnitude: p.h, + xcenter: Math.abs(Math.round(p.fx + (p.x / 2))), + ycenter: Math.abs(Math.round(p.fy + (p.y / 2))) + }; + }, + makeGesture: function(inType, inEvent, inCache) { + var vector, scale, rotation; + if (inCache) { + vector = inCache.vector; + scale = inCache.scale; + rotation = inCache.rotation; + } else { + var p = this.gesturePositions(inEvent); + vector = this.gestureVector(p); + scale = vector.magnitude / this.gesture.magnitude; + // gestureEvent.rotation is difference from the starting angle, clockwise + rotation = (360 + this.gestureAngle(p) - this.gesture.angle) % 360; + } + var e = enyo.clone(inEvent); + return enyo.mixin(e, { + type: inType, + scale: scale, + pageX: vector.xcenter, + pageY: vector.ycenter, + rotation: rotation + }); + } + }; +})(); diff --git a/enyo/source/touch/msevents.js b/enyo/source/touch/msevents.js new file mode 100644 index 0000000..11ad343 --- /dev/null +++ b/enyo/source/touch/msevents.js @@ -0,0 +1,93 @@ +//* @protected +(function() { + // add touch-specific gesture feature + var gesture = enyo.gesture; + if (window.navigator.msPointerEnabled) { + var msEvents = [ + "MSPointerDown", + "MSPointerUp", + "MSPointerMove", + "MSPointerOver", + "MSPointerOut", + "MSPointerCancel", + "MSGestureTap", + "MSGestureDoubleTap", + "MSGestureHold", + "MSGestureStart", + "MSGestureChange", + "MSGestureEnd" + ]; + enyo.forEach(msEvents, function(e) { + enyo.dispatcher.listen(document, e); + }); + // add our own MSPointer event handler + enyo.dispatcher.features.push(function(e) { + if (handlers[e.type] && e.isPrimary) { + handlers[e.type](e); + } + }); + // remove the default mouse event handlers + enyo.gesture.events = {}; + } + + var gestureNormalize = function(inType, inEvent) { + var e = enyo.clone(inEvent); + return enyo.mixin(e, { + pageX: inEvent.translationX || 0, + pageY: inEvent.translationY || 0, + // rad -> deg + rotation: (inEvent.rotation * (180 / Math.PI)) || 0, + type: inType, + srcEvent: inEvent, + preventDefault: gesture.preventDefault, + disablePrevention: gesture.disablePrevention + }); + }; + var makeEvent = function(inEvent) { + var e = enyo.clone(inEvent); + e.srcEvent = inEvent; + // normalize "mouse button" info + e.which = 1; + return e; + }; + + var handlers = { + // FIXME: need to register for gestures in MSPointerDown + // according to Microsoft docs + /*MSGestureStart: function(inEvent) { + enyo.dispatch(gestureNormalize("gesturestart", inEvent)); + }, + MSGestureChange: function(inEvent) { + enyo.dispatch(gestureNormalize("gesturechange", inEvent)); + }, + MSGestureEnd: function(inEvent) { + enyo.dispatch(gestureNormalize("gestureend", inEvent)); + },*/ + MSPointerDown: function(inEvent) { + var e = makeEvent(inEvent); + gesture.down(e); + }, + MSPointerUp: function(inEvent) { + var e = makeEvent(inEvent); + gesture.up(e); + }, + MSPointerMove: function(inEvent) { + var e = makeEvent(inEvent); + gesture.move(e); + }, + MSPointerCancel: function(inEvent) { + // FIXME: not really the same as touchend, as touch action + // was cancelled, but Enyo doesn't have that concept + var e = makeEvent(inEvent); + gesture.up(e); + }, + MSPointerOver: function(inEvent) { + var e = makeEvent(inEvent); + gesture.over(e); + }, + MSPointerOut: function(inEvent) { + var e = makeEvent(inEvent); + gesture.out(e); + } + }; +})(); \ No newline at end of file diff --git a/enyo/source/touch/package.js b/enyo/source/touch/package.js new file mode 100644 index 0000000..814e553 --- /dev/null +++ b/enyo/source/touch/package.js @@ -0,0 +1,14 @@ +enyo.depends( + "touch.js", + "msevents.js", + "gesture.js", + "ScrollMath.js", + "ScrollStrategy.js", + "Thumb.css", + "Thumb.js", + "TouchScrollStrategy.js", + "TranslateScrollStrategy.js", + "TransitionScrollStrategy.js", + "Scroller.js", + "Scroller.css" +); diff --git a/enyo/source/touch/touch.js b/enyo/source/touch/touch.js new file mode 100644 index 0000000..a628695 --- /dev/null +++ b/enyo/source/touch/touch.js @@ -0,0 +1,139 @@ +//* @protected +enyo.requiresWindow(function() { + // add touch-specific gesture feature + var gesture = enyo.gesture; + var oldevents = gesture.events; + // + gesture.events.touchstart = function(e) { + // for duration of this touch, only handle touch events. Old event + // structure will be restored during touchend. + gesture.events = touchGesture; + gesture.events.touchstart(e); + }; + // + var touchGesture = { + _touchCount: 0, + touchstart: function(inEvent) { + this._touchCount += inEvent.changedTouches.length; + this.excludedTarget = null; + var e = this.makeEvent(inEvent); + gesture.down(e); + // generate a new event object since over is a different event + e = this.makeEvent(inEvent); + this.overEvent = e; + gesture.over(e); + }, + touchmove: function(inEvent) { + enyo.job.stop("resetGestureEvents"); + // NOTE: allow user to supply a node to exclude from event + // target finding via the drag event. + var de = gesture.drag.dragEvent; + this.excludedTarget = de && de.dragInfo && de.dragInfo.node; + var e = this.makeEvent(inEvent); + gesture.move(e); + // prevent default document scrolling if enyo.bodyIsFitting == true + // avoid window scrolling by preventing default on this event + // note: this event can be made unpreventable (native scrollers do this) + if (enyo.bodyIsFitting) { + inEvent.preventDefault(); + } + // synthesize over and out (normally generated via mouseout) + if (this.overEvent && this.overEvent.target != e.target) { + this.overEvent.relatedTarget = e.target; + e.relatedTarget = this.overEvent.target; + gesture.out(this.overEvent); + gesture.over(e); + } + this.overEvent = e; + }, + touchend: function(inEvent) { + gesture.up(this.makeEvent(inEvent)); + // NOTE: in touch land, there is no distinction between + // a pointer enter/leave and a drag over/out. + // While it may make sense to send a leave event when a touch + // ends, it does not make sense to send a dragout. + // We avoid this by processing out after up, but + // this ordering is ad hoc. + gesture.out(this.overEvent); + // reset the event handlers back to the mouse-friendly ones after + // a short timeout. We can't do this directly in this handler + // because it messes up Android to handle the mouseup event. + // FIXME: for 2.1 release, conditional on platform being + // desktop Chrome, since we're seeing issues in PhoneGap with this + // code. + this._touchCount -= inEvent.changedTouches.length; + }, + // use mouseup after touches are done to reset event handling back to default + // --this works as long as no one did a preventDefault on the touch events + mouseup: function(e) { + if (this._touchCount === 0) { + this.sawMousedown = false; + gesture.events = oldevents; + } + }, + makeEvent: function(inEvent) { + var e = enyo.clone(inEvent.changedTouches[0]); + e.srcEvent = inEvent; + e.target = this.findTarget(e); + // normalize "mouse button" info + e.which = 1; + //enyo.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none")); + return e; + }, + calcNodeOffset: function(inNode) { + if (inNode.getBoundingClientRect) { + var o = inNode.getBoundingClientRect(); + return { + left: o.left, + top: o.top, + width: o.width, + height: o.height + }; + } + }, + findTarget: function(e) { + return document.elementFromPoint(e.clientX, e.clientY); + }, + // NOTE: will find only 1 element under the touch and + // will fail if an element is positioned outside the bounding box of its parent + findTargetTraverse: function(inNode, inX, inY) { + var n = inNode || document.body; + var o = this.calcNodeOffset(n); + if (o && n != this.excludedTarget) { + var x = inX - o.left; + var y = inY - o.top; + //enyo.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")"); + if (x>0 && y>0 && x<=o.width && y<=o.height) { + //enyo.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")"); + var target; + for (var n$=n.childNodes, i=n$.length-1, c; (c=n$[i]); i--) { + target = this.findTargetTraverse(c, inX, inY); + if (target) { + return target; + } + } + return n; + } + } + }, + connect: function() { + enyo.forEach(['ontouchstart', 'ontouchmove', 'ontouchend', 'ongesturestart', 'ongesturechange', 'ongestureend'], function(e) { + document[e] = enyo.dispatch; + }); + if (enyo.platform.androidChrome <= 18 || enyo.platform.silk === 2) { + // HACK: on Chrome for Android v18 on devices with higher density displays, + // document.elementFromPoint expects screen coordinates, not document ones + // bug also appears on Kindle Fire HD + this.findTarget = function(e) { + return document.elementFromPoint(e.screenX, e.screenY); + }; + } else if (!document.elementFromPoint) { + this.findTarget = function(e) { + return this.findTargetTraverse(null, e.clientX, e.clientY); + }; + } + } + }; + // + touchGesture.connect(); +}); \ No newline at end of file diff --git a/enyo/source/ui/Animator.js b/enyo/source/ui/Animator.js new file mode 100644 index 0000000..5f67121 --- /dev/null +++ b/enyo/source/ui/Animator.js @@ -0,0 +1,132 @@ +/** + _enyo.Animator_ is a basic animation component. Call _play_ to start the + animation. The animation will run for the period (in milliseconds) specified + by its _duration_ property. The _onStep_ event will fire in quick + succession and should be handled to do something based on the _value_ + property. + + The _value_ property will progress from _startValue_ to _endValue_ during + the animation based on the function referenced by the _easingFunction_ + property. The _stop_ method may be called to manually stop an in-progress + animation; calling it will fire the _onStop_ event. When an animation + completes normally, the _onEnd_ event is fired. + + Event handlers may be specified as functions. If specified, the handler + function will be used to handle the event directly, without sending the + event to its owner or bubbling it. The _context_ property can be used to + call the supplied event functions in a particular "this" context. +*/ +enyo.kind({ + name: "enyo.Animator", + kind: "Component", + published: { + //* Animation duration in milliseconds + duration: 350, + //* Value of _value_ property at the beginning of an animation + startValue: 0, + //* Value of _value_ property at the end of an animation + endValue: 1, + //* Node that must be visible in order for the animation to continue. + //* This reference is destroyed when the animation ceases. + node: null, + //* Function that determines how the animation progresses from + //* _startValue_ to _endValue_ + easingFunction: enyo.easing.cubicOut + }, + events: { + //* Fires when an animation step occurs. + onStep: "", + //* Fires when the animation finishes normally. + onEnd: "", + //* Fires when the animation is prematurely stopped. + onStop: "" + }, + //* @protected + constructed: function() { + this.inherited(arguments); + this._next = enyo.bind(this, "next"); + }, + destroy: function() { + this.stop(); + this.inherited(arguments); + }, + //* @public + //* Plays the animation. + //* For convenience, _inProps_ will be mixed directly into this object. + play: function(inProps) { + this.stop(); + this.reversed = false; + if (inProps) { + enyo.mixin(this, inProps); + } + this.t0 = this.t1 = enyo.now(); + this.value = this.startValue; + this.job = true; + this.next(); + return this; + }, + //* Stops the animation and fires the _onStop_ event. + stop: function() { + if (this.isAnimating()) { + this.cancel(); + this.fire("onStop"); + return this; + } + }, + //* Reverses the direction of a running animation; returns self if animating. + reverse: function() { + if (this.isAnimating()) { + this.reversed = !this.reversed; + var now = this.t1 = enyo.now(); + // adjust start time (t0) to allow for animation done so far to replay + var elapsed = now - this.t0; + this.t0 = now + elapsed - this.duration; + // swap start and end values + var startValue = this.startValue; + this.startValue = this.endValue; + this.endValue = startValue; + return this; + } + }, + //* Returns true if animation is in progress. + isAnimating: function() { + return Boolean(this.job); + }, + //* @protected + requestNext: function() { + this.job = enyo.requestAnimationFrame(this._next, this.node); + }, + cancel: function() { + enyo.cancelRequestAnimationFrame(this.job); + this.node = null; + this.job = null; + }, + shouldEnd: function() { + return (this.dt >= this.duration); + }, + next: function() { + this.t1 = enyo.now(); + this.dt = this.t1 - this.t0; + // time independent + var f = this.fraction = enyo.easedLerp(this.t0, this.duration, this.easingFunction, this.reversed); + this.value = this.startValue + f * (this.endValue - this.startValue); + if (f >= 1 || this.shouldEnd()) { + this.value = this.endValue; + this.fraction = 1; + this.fire("onStep"); + this.fire("onEnd"); + this.cancel(); + } else { + this.fire("onStep"); + this.requestNext(); + } + }, + fire: function(inEventName) { + var fn = this[inEventName]; + if (enyo.isString(fn)) { + this.bubble(inEventName); + } else if (fn) { + fn.call(this.context || window, this); + } + } +}); diff --git a/enyo/source/ui/BaseLayout.js b/enyo/source/ui/BaseLayout.js new file mode 100644 index 0000000..d3eae5f --- /dev/null +++ b/enyo/source/ui/BaseLayout.js @@ -0,0 +1,22 @@ +/** + _enyo.BaseLayout_ provides a basic layout strategy, positioning contained + components with the _enyo-positioned_ layoutClass. In addition, it adjusts + the layout when _reflow_ is called, removing or adding the _enyo-fit_ class + for components that have set the _fit_ property. +*/ +enyo.kind({ + name: "enyo.BaseLayout", + kind: enyo.Layout, + layoutClass: "enyo-positioned", + //* Adds or removes the _enyo-fit_ class for components whose _fit_ property + //* has been set. + reflow: function() { + enyo.forEach(this.container.children, function(c) { + if (c.fit !== null) { + c.addRemoveClass("enyo-fit", c.fit); + } + }, this); + } +}); + +//enyo.Control.prototype.layoutKind = "enyo.BaseLayout"; \ No newline at end of file diff --git a/enyo/source/ui/Button.js b/enyo/source/ui/Button.js new file mode 100644 index 0000000..4de4735 --- /dev/null +++ b/enyo/source/ui/Button.js @@ -0,0 +1,42 @@ +/** + _enyo.Button_ implements an HTML button, with support for grouping using + enyo.Group. + + For more information, see the documentation on + Buttons in the + Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Button", + //* @protected + kind: enyo.ToolDecorator, + tag: "button", + attributes: { + // set to button, as default is "submit" which can cause unexpected + // problems when controls are used inside a form + type: "button" + }, + //* @public + published: { + //* When true, button is shown as disabled and does not generate tap + //* events + disabled: false + }, + //* @protected + create: function() { + this.inherited(arguments); + this.disabledChanged(); + }, + disabledChanged: function() { + this.setAttribute("disabled", this.disabled); + }, + tap: function() { + if (this.disabled) { + // work around for platforms like Chrome on Android or Opera that send + // mouseup to disabled form controls + return true; + } else { + this.setActive(true); + } + } +}); diff --git a/enyo/source/ui/Checkbox.js b/enyo/source/ui/Checkbox.js new file mode 100644 index 0000000..c9d7e60 --- /dev/null +++ b/enyo/source/ui/Checkbox.js @@ -0,0 +1,77 @@ +/** + _enyo.Checkbox_ implements an HTML checkbox input, with support for grouping. +*/ +enyo.kind({ + name: "enyo.Checkbox", + kind: enyo.Input, + classes: "enyo-checkbox", + events: { + //* Fires when checkbox is tapped. + onActivate: "" + }, + published: { + //* Value of checkbox; true if checked + checked: false, + //* Group API requirement for determining selected item + active: false, + //* @protected + type: "checkbox" + }, + //* @protected + // disable classes inherited from enyo.Input + kindClasses: "", + handlers: { + onchange: "change", + onclick: "click" + }, + create: function() { + this.inherited(arguments); + }, + rendered: function() { + this.inherited(arguments); + if (this.active) { + this.activeChanged(); + } + this.checkedChanged(); + }, + // instance 'checked' property is linked to DOM 'checked' property + getChecked: function() { + return enyo.isTrue(this.getNodeProperty("checked", this.checked)); + }, + checkedChanged: function() { + this.setNodeProperty("checked", this.checked); + this.setAttribute("checked", this.checked ? "checked" : ""); + this.setActive(this.checked); + }, + // active property, and onActivate event, are part of "GroupItem" interface + // that we support in this object + activeChanged: function() { + this.active = enyo.isTrue(this.active); + this.setChecked(this.active); + this.bubble("onActivate"); + }, + // all input type controls support 'value' property + setValue: function(inValue) { + this.setChecked(enyo.isTrue(inValue)); + }, + getValue: function() { + return this.getChecked(); + }, + valueChanged: function() { + // inherited behavior is to set "value" attribute and node-property + // which does not apply to checkbox (uses "checked") so + // we squelch the inherited method + }, + change: function() { + this.setActive(this.getChecked()); + }, + click: function(inSender, inEvent) { + // Various versions of IE (notably IE8) do not fire 'onchange' for + // checkboxes, so we discern change via 'click'. + // Note: keyboard interaction (e.g. pressing space when focused) fires + // a click event. + if (enyo.platform.ie <= 8) { + this.bubble("onchange", inEvent); + } + } +}); diff --git a/enyo/source/ui/DragAvatar.js b/enyo/source/ui/DragAvatar.js new file mode 100644 index 0000000..ec49233 --- /dev/null +++ b/enyo/source/ui/DragAvatar.js @@ -0,0 +1,90 @@ +//* @protected +enyo.kind({ + name: "enyo._DragAvatar", + style: "position: absolute; z-index: 10; pointer-events: none; cursor: move;", + showing: false, + showingChanged: function() { + this.inherited(arguments); + document.body.style.cursor = this.showing ? "move" : null; + } +}); + +//* @public +/** + _enyo.DragAvatar_ creates a control to follow the pointer when dragging. It + automatically displays the avatar control when the user drags, and updates + its position relative to the current pointer location. + + enyo.kind({ + name: "App", + handlers: { + ondrag: "drag", + ondragfinish: "dragFinish", + }, + components: [ + {name:"dragAvatar", kind:"DragAvatar", + components: [{tag: "img", src: "images/icon.png"}] + } + ], + drag: function(inSender, inEvent) { + this.$.dragAvatar.drag(inEvent); + }, + dragFinish: function(inSender, inEvent) { + this.$.dragAvatar.hide(); + } + }); +*/ +enyo.kind({ + name: "enyo.DragAvatar", + kind: enyo.Component, + published: { + //* Current visibility state of the DragAvatar + showing: false, + /** + Distance (in pixels) along the horizontal axis between the current + drag position and where the avatar control is displayed. + */ + offsetX: 20, + /** + Distance (in pixels) along the vertical axis between the current + drag position and where the avatar control is displayed. + */ + offsetY: 30 + }, + //* @protected + initComponents: function() { + this.avatarComponents = this.components; + this.components = null; + this.inherited(arguments); + }, + requireAvatar: function() { + // FIXME: there is nobody to call teardownRender on this.avatar + // if document.body.innerHTML has been written over, his node is invalid + // we should have a trap for this condition here + if (!this.avatar) { + this.avatar = this.createComponent({kind: enyo._DragAvatar, parentNode: document.body, showing: false, components: this.avatarComponents}).render(); + } + }, + showingChanged: function() { + this.avatar.setShowing(this.showing); + document.body.style.cursor = this.showing ? "move" : null; + }, + //* @public + /** + Instantiates the avatar control (if necessary), determines correct + position, and calls _show_ to make it visible. + */ + drag: function(inEvent) { + this.requireAvatar(); + this.avatar.setBounds({top: inEvent.pageY - this.offsetY, left: inEvent.pageX + this.offsetX}); + this.show(); + }, + //* Shows the DragAvatar. + show: function() { + this.setShowing(true); + }, + //* Hides the DragAvatar. + hide: function() { + this.setShowing(false); + } +}); diff --git a/enyo/source/ui/FloatingLayer.js b/enyo/source/ui/FloatingLayer.js new file mode 100644 index 0000000..ff78308 --- /dev/null +++ b/enyo/source/ui/FloatingLayer.js @@ -0,0 +1,38 @@ +/** + _enyo.FloatingLayer_ is a control that provides a layer for controls that + should be displayed above an application. + The FloatingLayer singleton can be set as a control's parent to have the + control float above an application, e.g.: + + create: function() { + this.inherited(arguments); + this.setParent(enyo.floatingLayer); + } + + Note: It's not intended that users create instances of _enyo.FloatingLayer_. +*/ +//* @protected +enyo.kind({ + name: "enyo.FloatingLayer", + //* @protected + create: function() { + this.inherited(arguments); + this.setParent(null); + }, + render: function() { + this.parentNode = document.body; + return this.inherited(arguments); + }, + generateInnerHtml: function() { + return ""; + }, + beforeChildRender: function() { + if (!this.hasNode()) { + this.render(); + } + }, + teardownChildren: function() { + } +}); + +enyo.floatingLayer = new enyo.FloatingLayer(); \ No newline at end of file diff --git a/enyo/source/ui/Group.js b/enyo/source/ui/Group.js new file mode 100644 index 0000000..f9ccd7e --- /dev/null +++ b/enyo/source/ui/Group.js @@ -0,0 +1,46 @@ +/** + _enyo.Group_ provides a wrapper around multiple elements. It enables the + creation of radio groups from arbitrary components supporting the + [GroupItem](#enyo.GroupItem) API. +*/ +enyo.kind({ + name: "enyo.Group", + published: { + /** + If true, only one GroupItem in the component list may be active at + a given time. + */ + highlander: true, + //* The control that was last selected + active: null + }, + //* @protected + handlers: { + onActivate: "activate" + }, + activate: function(inSender, inEvent) { + if (this.highlander) { + // deactivation messages are ignored unless it's an attempt + // to deactivate the highlander + if (!inEvent.originator.active) { + // this clause prevents deactivating a grouped item once it's been active. + // the only proper way to deactivate a grouped item is to choose a new + // highlander. + if (inEvent.originator == this.active) { + this.active.setActive(true); + } + } else { + this.setActive(inEvent.originator); + } + } + }, + activeChanged: function(inOld) { + if (inOld) { + inOld.setActive(false); + inOld.removeClass("active"); + } + if (this.active) { + this.active.addClass("active"); + } + } +}); diff --git a/enyo/source/ui/GroupItem.js b/enyo/source/ui/GroupItem.js new file mode 100644 index 0000000..673ad77 --- /dev/null +++ b/enyo/source/ui/GroupItem.js @@ -0,0 +1,28 @@ +/** + _enyo.GroupItem_ is the base kind for the Grouping API. It manages the + active state of the component (or the inheriting component). A subkind may + call _setActive_ to set the _active_ property to the desired state; this + will additionally bubble an _onActivate_ event, which can be handled as + needed by the containing components. This is useful for creating groups of + items whose state should be managed as a group. + + For an example of how this works, see the + enyo.Group kind, which enables the creation of + radio groups from arbitrary components that support the Grouping API. +*/ + +enyo.kind({ + name: "enyo.GroupItem", + published: { + //* True if the item is currently selected + active: false + }, + //* @protected + rendered: function() { + this.inherited(arguments); + this.activeChanged(); + }, + activeChanged: function() { + this.bubble("onActivate"); + } +}); diff --git a/enyo/source/ui/Image.js b/enyo/source/ui/Image.js new file mode 100644 index 0000000..8a72bf0 --- /dev/null +++ b/enyo/source/ui/Image.js @@ -0,0 +1,28 @@ +/** + _enyo.Image_ implements an HTML <img> element and, optionally, bubbles + the _onload_ and _onerror_ events. Image dragging is suppressed by default, + so as not to interfere with touch interfaces. +*/ +enyo.kind({ + name: "enyo.Image", + //* When true, no _onload_ or _onerror_ event handlers will be created + noEvents: false, + //* @protected + tag: "img", + attributes: { + // note: draggable attribute takes one of these String values: "true", "false", "auto" + // (Boolean _false_ would remove the attribute) + draggable: "false" + }, + create: function() { + if (this.noEvents) { + delete this.attributes.onload; + delete this.attributes.onerror; + } + this.inherited(arguments); + }, + rendered: function() { + this.inherited(arguments); + enyo.makeBubble(this, "load", "error"); + } +}); diff --git a/enyo/source/ui/Input.js b/enyo/source/ui/Input.js new file mode 100644 index 0000000..d13e068 --- /dev/null +++ b/enyo/source/ui/Input.js @@ -0,0 +1,148 @@ +/** + _enyo.Input_ implements an HTML <input> element with cross-platform + support for change events. + + You can listen for _oninput_ and _onchange_ DOM events from this control + to know when the text inside has been modified. _oninput_ fires immediately, + while _onchange_ fires when the text has changed and the input subsequently + loses focus. + + For more information, see the documentation on + [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.Input", + published: { + /** + Value of the input. Use this property only to initialize the value. + Call _getValue_ and _setValue_ to manipulate the value at runtime. + */ + value: "", + //* Text to display when the input is empty + placeholder: "", + /** + Type of input; if not specified, it's treated as "text". It can + be anything specified for the _type_ attribute in the HTML + specification, including "url", "email", "search", or "number". + */ + type: "", + /** + When true, prevents input into the control. This maps to the + _disabled_ DOM attribute. + */ + disabled: false, + //* When true, select the contents of the input when it gains focus. + selectOnFocus: false + }, + events: { + //* Fires when the input is disabled or enabled. + onDisabledChange: "" + }, + //* Set to true to focus this control when it is rendered + defaultFocus: false, + //* @protected + tag: "input", + classes: "enyo-input", + handlers: { + onfocus: "focused", + oninput: "input", + onclear: "clear", + ondragstart: "dragstart" + }, + create: function() { + if (enyo.platform.ie) { + this.handlers.onkeyup = "iekeyup"; + } + if (enyo.platform.windowsPhone) { + this.handlers.onkeydown = "iekeydown"; + } + this.inherited(arguments); + this.placeholderChanged(); + // prevent overriding a custom attribute with null + if (this.type) { + this.typeChanged(); + } + this.valueChanged(); + }, + rendered: function() { + this.inherited(arguments); + + enyo.makeBubble(this, "focus", "blur"); + + //Force onchange event to be bubbled inside Enyo for IE8 + if(enyo.platform.ie == 8){ + this.setAttribute("onchange", enyo.bubbler); + } + + this.disabledChanged(); + if (this.defaultFocus) { + this.focus(); + } + }, + typeChanged: function() { + this.setAttribute("type", this.type); + }, + placeholderChanged: function() { + this.setAttribute("placeholder", this.placeholder); + }, + disabledChanged: function() { + this.setAttribute("disabled", this.disabled); + this.bubble("onDisabledChange"); + }, + getValue: function() { + return this.getNodeProperty("value", this.value); + }, + valueChanged: function() { + this.setAttribute("value", this.value); + this.setNodeProperty("value", this.value); + }, + iekeyup: function(inSender, inEvent) { + var ie = enyo.platform.ie, kc = inEvent.keyCode; + // input event missing on ie 8, fails to fire on backspace and delete keys in ie 9 + if (ie <= 8 || (ie == 9 && (kc == 8 || kc == 46))) { + this.bubble("oninput", inEvent); + } + }, + iekeydown: function(inSender, inEvent) { + var wp = enyo.platform.windowsPhone, kc = inEvent.keyCode, dt = inEvent.dispatchTarget; + // onchange event fails to fire on enter key for Windows Phone 8, so we force blur + if (wp <= 8 && kc == 13 && this.tag == "input" && dt.hasNode()) { + dt.node.blur(); + } + }, + clear: function() { + this.setValue(""); + }, + focus: function() { + if (this.hasNode()) { + this.node.focus(); + } + }, + //* Returns true if the Input is focused. + hasFocus: function() { + if (this.hasNode()) { + return document.activeElement === this.node; + } + }, + // note: we disallow dragging of an input to allow text selection on all platforms + dragstart: function() { + return this.hasFocus(); + }, + focused: function() { + if (this.selectOnFocus) { + enyo.asyncMethod(this, "selectContents"); + } + }, + selectContents: function() { + var n = this.hasNode(); + + if (n && n.setSelectionRange) { + n.setSelectionRange(0, n.value.length); + } else if (n && n.createTextRange) { + var r = n.createTextRange(); + r.expand("textedit"); + r.select(); + } + } +}); diff --git a/enyo/source/ui/Popup.js b/enyo/source/ui/Popup.js new file mode 100644 index 0000000..96f06fe --- /dev/null +++ b/enyo/source/ui/Popup.js @@ -0,0 +1,303 @@ +/** + _enyo.Popup_ is a control used to display certain content on top of other + content. + + Popups are initially hidden on creation; they can be shown by calling the + _show_ method and re-hidden by calling _hide_. Popups may be centered using + the _centered_ property; if not centered, they should be given a specific + position. + + A popup may be optionally floated above all application content by setting + its _floating_ property to _true_. This has the advantage of guaranteeing + that the popup will be displayed on top of other content. This usage is + appropriate when the popup does not need to scroll along with other content. + + For more information, see the documentation on + [Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer + Guide. + */ +enyo.kind({ + name: "enyo.Popup", + classes: "enyo-popup enyo-no-touch-action", + published: { + //* Set to true to prevent controls outside the popup from receiving + //* events while the popup is showing + modal: false, + //* By default, the popup will hide when the user taps outside it or + //* presses ESC. Set to false to prevent this behavior. + autoDismiss: true, + //* Set to true to render the popup in a floating layer outside of other + //* controls. This can be used to guarantee that the popup will be + //* shown on top of other controls. + floating: false, + //* Set to true to automatically center the popup in the middle of the viewport + centered: false + }, + //* @protected + showing: false, + handlers: { + ondown: "down", + onkeydown: "keydown", + ondragstart: "dragstart", + onfocus: "focus", + onblur: "blur", + onRequestShow: "requestShow", + onRequestHide: "requestHide" + }, + captureEvents: true, + //* @public + events: { + //* Fires after the popup is shown. + onShow: "", + //* Fires after the popup is hidden. + onHide: "" + }, + //* @protected + tools: [ + {kind: "Signals", onKeydown: "keydown"} + ], + create: function() { + this.inherited(arguments); + /*if (this.floating) { + this.setParent(enyo.floatingLayer); + }*/ + this.canGenerate = !this.floating; + }, + render: function() { + if (this.floating) { + if (!enyo.floatingLayer.hasNode()) { + enyo.floatingLayer.render(); + } + this.parentNode = enyo.floatingLayer.hasNode(); + } + this.inherited(arguments); + }, + destroy: function() { + if (this.showing) { + this.release(); + } + this.inherited(arguments); + }, + + reflow: function() { + this.updatePosition(); + this.inherited(arguments); + }, + calcViewportSize: function() { + if (window.innerWidth) { + return { + width: window.innerWidth, + height: window.innerHeight + }; + } else { + var e = document.documentElement; + return { + width: e.offsetWidth, + height: e.offsetHeight + }; + } + }, + updatePosition: function() { + var d = this.calcViewportSize(); + var b = this.getBounds(); + + if (this.targetPosition) { + // For brevity's sake... + var p = this.targetPosition; + + // Test and optionally adjust our target bounds (only first is commented, because logic is effectively identical for all scenarios) + if (typeof p.left === 'number') { + // If popup will be outside window bounds, switch anchor + if (p.left + b.width > d.width) { + if (p.left - b.width >= 0) { + // Switching to right corner will fit in window + p.right = d.width - p.left; + } else { + // Neither corner will work; stick at side of window + p.right = 0; + } + p.left = null; + } else { + p.right = null; + } + } else if (typeof p.right === 'number') { + if (p.right + b.width > d.width) { + if (p.right - b.width >= 0) { + p.left = d.width - p.right; + } else { + p.left = 0; + } + p.right = null; + } else { + p.left = null; + } + } + + if (typeof p.top === 'number') { + if (p.top + b.height > d.height) { + if (p.top - b.height >= 0) { + p.bottom = d.height - p.top; + } else { + p.bottom = 0; + } + p.top = null; + } else { + p.bottom = null; + } + } else if (typeof p.bottom === 'number') { + if (p.bottom + b.height > d.height) { + if (p.bottom - b.height >= 0) { + p.top = d.height - p.bottom; + } else { + p.top = 0; + } + p.bottom = null; + } else { + p.top = null; + } + } + + // 'initial' values are necessary to override positioning rules in the CSS + this.addStyles('left: ' + (p.left !== null ? p.left + 'px' : 'initial') + '; right: ' + (p.right !== null ? p.right + 'px' : 'initial') + '; top: ' + (p.top !== null ? p.top + 'px' : 'initial') + '; bottom: ' + (p.bottom !== null ? p.bottom + 'px' : 'initial') + ';'); + } else if (this.centered) { + this.addStyles( "top: " + Math.max( ( ( d.height - b.height ) / 2 ), 0 ) + "px; left: " + Math.max( ( ( d.width - b.width ) / 2 ), 0 ) + "px;" ); + } + }, + showingChanged: function() { + // auto render when shown. + if (this.floating && this.showing && !this.hasNode()) { + this.render(); + } + // hide while sizing, and move to top corner for accurate sizing + if (this.centered || this.targetPosition) { + this.applyStyle("visibility", "hidden"); + this.addStyles("top: 0px; left: 0px; right: initial; bottom: initial;"); + } + this.inherited(arguments); + if (this.showing) { + this.resized(); + if (this.captureEvents) { + this.capture(); + } + } else { + if (this.captureEvents) { + this.release(); + } + } + // show after sizing + if (this.centered || this.targetPosition) { + this.applyStyle("visibility", null); + } + // events desired due to programmatic show/hide + if (this.hasNode()) { + this[this.showing ? "doShow" : "doHide"](); + } + }, + capture: function() { + enyo.dispatcher.capture(this, !this.modal); + }, + release: function() { + enyo.dispatcher.release(); + }, + down: function(inSender, inEvent) { + //record the down event to verify in tap + this.downEvent = inEvent; + + // prevent focus from shifting outside the popup when modal. + if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) { + inEvent.preventDefault(); + } + }, + tap: function(inSender, inEvent) { + // dismiss on tap if property is set and click started & ended outside the popup + if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this)) && this.downEvent && + (!this.downEvent.dispatchTarget.isDescendantOf(this))) { + this.downEvent = null; + this.hide(); + return true; + } + }, + // if a drag event occurs outside a popup, hide + dragstart: function(inSender, inEvent) { + var inScope = (inEvent.dispatchTarget === this || inEvent.dispatchTarget.isDescendantOf(this)); + if (inSender.autoDismiss && !inScope) { + inSender.setShowing(false); + } + return true; + }, + keydown: function(inSender, inEvent) { + if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) { + this.hide(); + } + }, + // If something inside the popup blurred, keep track of it. + blur: function(inSender, inEvent) { + if (inEvent.dispatchTarget.isDescendantOf(this)) { + this.lastFocus = inEvent.originator; + } + }, + // When something outside the popup focuses (e.g., due to tab key), focus our last focused control. + focus: function(inSender, inEvent) { + var dt = inEvent.dispatchTarget; + if (this.modal && !dt.isDescendantOf(this)) { + if (dt.hasNode()) { + dt.node.blur(); + } + var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode(); + if (n) { + n.focus(); + } + } + }, + requestShow: function(inSender, inEvent) { + this.show(); + return true; + }, + requestHide: function(inSender, inEvent) { + this.hide(); + return true; + }, + + //* @public + /** + Open at the location of a mouse event (_inEvent_). The popup's + position is automatically constrained so that it does not + display outside the viewport, and defaults to anchoring the top + left corner of the popup to the mouse event. + + _inOffset_ is an optional object which may contain left and top + properties to specify an offset relative to the location the + popup would otherwise be positioned. + */ + showAtEvent: function(inEvent, inOffset) { + // Calculate our ideal target based on the event position and offset + var p = { + left: inEvent.centerX || inEvent.clientX || inEvent.pageX, + top: inEvent.centerY || inEvent.clientY || inEvent.pageY + }; + if (inOffset) { + p.left += inOffset.left || 0; + p.top += inOffset.top || 0; + } + + this.showAtPosition(p); + }, + + /** + Open the popup at a specific position. The final location + of the popup will be automatically constrained so that it does not + display outside the viewport. + + _inPosition_ is an object which may contain left, top, bottom, + and right properties to specify where the popup will be anchored. + If both left and right are included, the popup will preference left + (same for top vs. bottom). + */ + showAtPosition: function(inPosition) { + // Save our target position for later processing + this.targetPosition = inPosition; + + // Show the dialog + this.show(); + } +}); diff --git a/enyo/source/ui/Repeater.js b/enyo/source/ui/Repeater.js new file mode 100644 index 0000000..fce6ec2 --- /dev/null +++ b/enyo/source/ui/Repeater.js @@ -0,0 +1,108 @@ +/** + _enyo.Repeater_ is a simple control for making lists of items. + + The components of a repeater are copied for each item created, and are + wrapped in a control that keeps the state of the item index. + + Example: + + {kind: "Repeater", count: 2, onSetupItem: "setImageSource", components: [ + {kind: "Image"} + ]} + + setImageSource: function(inSender, inEvent) { + var index = inEvent.index; + var item = inEvent.item; + item.$.image.setSrc(this.imageSources[index]); + return true; + } + + Be sure to return _true_ from your _onSetupItem_ handler to avoid having + other event handlers further up the tree try to modify your item control. + + For more information, see the documentation on + [Lists](https://github.com/enyojs/enyo/wiki/Lists) in the Enyo Developer + Guide. +*/ +enyo.kind({ + name: "enyo.Repeater", + published: { + //* Number of items + count: 0 + }, + events: { + /** + Fires when each item is created. + + _inEvent.index_ contains the item's index. + + _inEvent.item_ contains the item control, for decoration. + */ + onSetupItem: "" + }, + create: function() { + this.inherited(arguments); + this.countChanged(); + }, + //* @protected + initComponents: function() { + this.itemComponents = this.components || this.kindComponents; + this.components = this.kindComponents = null; + this.inherited(arguments); + }, + setCount: function(inCount) { + this.setPropertyValue("count", inCount, "countChanged"); + }, + countChanged: function() { + this.build(); + }, + itemAtIndex: function(inIndex) { + return this.controlAtIndex(inIndex); + }, + //* @public + /** Renders the collection of items. This will delete any existing items and + recreate the repeater if called after the repeater has been rendered. + This is called automatically if _setCount_ is called, even if the count + remains the same. + */ + build: function() { + this.destroyClientControls(); + for (var i=0, c; i"); + document.execCommand("insertHTML", false, v); + } + } +}); diff --git a/enyo/source/ui/Select.js b/enyo/source/ui/Select.js new file mode 100644 index 0000000..4e01311 --- /dev/null +++ b/enyo/source/ui/Select.js @@ -0,0 +1,116 @@ +/** + _enyo.Select_ implements an HTML selection widget, using + [enyo.Option](#enyo.Option) kinds by default. + + Example: + + {kind: "Select", onchange: "selectChanged", components: [ + {content: "Descending", value: "d"}, + {content: "Ascending", value: "a"} + ]} + + selectChanged: function(inSender, inEvent) { + var s = inSender.getValue(); + if (s == "d") { + this.sortListDescending(); + } else { + this.sortListAscending(); + } + } + + Note: This uses the `, rerender parent instead + // http://support.microsoft.com/default.aspx?scid=kb;en-us;276228 + if (enyo.platform.ie) { + this.parent.render(); + } else { + this.inherited(arguments); + } + }, + //* @public + //* Returns the value of the selected option. + getValue: function() { + if (this.hasNode()) { + return this.node.value; + } + } +}); + +/** + _enyo.Option_ implements the options in an HTML select widget. +*/ +enyo.kind({ + name: "enyo.Option", + published: { + //* Value of the option + value: "" + }, + //* @protected + tag: "option", + create: function() { + this.inherited(arguments); + this.valueChanged(); + }, + valueChanged: function() { + this.setAttribute("value", this.value); + } +}); + +/** + _enyo.OptionGroup_ allows for the grouping of options in a select widget, + and for the disabling of blocks of options. +*/ +enyo.kind({ + name: "enyo.OptionGroup", + published: { + label: "" + }, + //* @protected + tag: "optgroup", + defaultKind: "enyo.Option", + create: function() { + this.inherited(arguments); + this.labelChanged(); + }, + labelChanged: function() { + this.setAttribute("label", this.label); + } +}); diff --git a/enyo/source/ui/Selection.js b/enyo/source/ui/Selection.js new file mode 100644 index 0000000..a0943f0 --- /dev/null +++ b/enyo/source/ui/Selection.js @@ -0,0 +1,171 @@ +/** + _enyo.Selection_ is used to manage row selection state for lists. It + provides selection state management for both single-select and multi-select + lists. + + // The following is an excerpt from enyo.FlyweightRepeater. + enyo.kind({ + name: "enyo.FlyweightRepeater", + ... + components: [ + {kind: "Selection", onSelect: "selectDeselect", onDeselect: "selectDeselect"}, + ... + ], + tap: function(inSender, inEvent) { + ... + // mark the tapped row as selected + this.$.selection.select(inEvent.index); + ... + }, + selectDeselect: function(inSender, inEvent) { + // this is where a row selection highlight might be applied + this.renderRow(inEvent.key); + } + ... + }) +*/ +enyo.kind({ + name: "enyo.Selection", + kind: enyo.Component, + published: { + //* If true, multiple selections are allowed + multi: false + }, + events: { + /** + Fires when an item is selected. + + {kind: "Selection", onSelect: "selectRow"... + ... + selectRow: function(inSender, inEvent) { + ... + + _inEvent.key_ is whatever key was used to register the selection + (usually a row index). + + _inEvent.data_ references data registered with this key by the code + that made the original selection. + */ + onSelect: "", + /** + Fires when an item is deselected. + + {kind: "Selection", onSelect: "deselectRow"... + ... + deselectRow: function(inSender, inEvent) + ... + + _inEvent.key_ is whatever key was used to request the deselection + (usually a row index). + + _inEvent.data_ references data registered with this key by the code + that made the selection. + */ + onDeselect: "", + //* Fires when selection changes (but not when selection is cleared). + onChange: "" + }, + //* @protected + create: function() { + this.clear(); + this.inherited(arguments); + }, + multiChanged: function() { + if (!this.multi) { + this.clear(); + } + this.doChange(); + }, + highlander: function(inKey) { + if (!this.multi) { + this.deselect(this.lastSelected); + } + }, + //* @public + //* Removes all selections. + clear: function() { + this.selected = {}; + }, + //* Returns true if the _inKey_ row is selected. + isSelected: function(inKey) { + return this.selected[inKey]; + }, + /** + Manually sets a row's state to selected or unselected. + + _inData_ is an optional data object to store in the selection for + that key that will be sent with the _onSelect_ or _onDeselect_ events. + If not used, the data will be set to 'true'. + */ + setByKey: function(inKey, inSelected, inData) { + if (inSelected) { + this.selected[inKey] = (inData || true); + this.lastSelected = inKey; + this.doSelect({key: inKey, data: this.selected[inKey]}); + } else { + var was = this.isSelected(inKey); + delete this.selected[inKey]; + this.doDeselect({key: inKey, data: was}); + } + this.doChange(); + }, + //* Deselects a row. + deselect: function(inKey) { + if (this.isSelected(inKey)) { + this.setByKey(inKey, false); + } + }, + /** + Selects a row. If the _multi_ property is set to false, _select_ will + also deselect the previous selection. + + _inData_ is an optional data object to store in the selection for + that key that will be sent with the _onSelect_ or _onDeselect_ events. + If not used, the data will be set to 'true'. + */ + select: function(inKey, inData) { + if (this.multi) { + this.setByKey(inKey, !this.isSelected(inKey), inData); + } else if (!this.isSelected(inKey)) { + this.highlander(); + this.setByKey(inKey, true, inData); + } + }, + /** + Toggles selection state for a row. If the _multi_ property is set to + false, toggling a selection on will deselect the previous selection. + + _inData_ is an optional data object to store in the selection for + that key that will be sent with the _onSelect_ or _onDeselect_ events. + If not used, the data will be set to 'true'. + */ + toggle: function(inKey, inData) { + if (!this.multi && this.lastSelected != inKey) { + this.deselect(this.lastSelected); + } + this.setByKey(inKey, !this.isSelected(inKey), inData); + }, + /** + Returns the selection as a hash in which each selected item has a value; + unselected items are undefined. + */ + getSelected: function() { + return this.selected; + }, + /** + Remove a row that's included in the selection set. If this row is + selected, it will be unselected. Any rows above this row will + have their keys value reduced by one. + */ + remove: function(inKey) { + var newSelected = {}; + for (var row in this.selected) { + if (row < inKey) { + newSelected[row] = this.selected[row]; + } else if (row > inKey) { + newSelected[row - 1] = this.selected[row]; + } + } + this.selected = newSelected; + } +}); \ No newline at end of file diff --git a/enyo/source/ui/Table.js b/enyo/source/ui/Table.js new file mode 100644 index 0000000..40f77d9 --- /dev/null +++ b/enyo/source/ui/Table.js @@ -0,0 +1,36 @@ +/* + TODO: Won't work in IE8 because we can't set innerHTML + on table elements. We'll need to fall back to divs with + table display styles applied. + + Should also facade certain useful table functionality + (specific set TBD). +*/ + +/** + _enyo.Table_ implements an HTML <table> element. + This is a work in progress. +*/ +enyo.kind({ + name: "enyo.Table", + tag: "table", + attributes: {cellpadding: "0", cellspacing: "0"}, + defaultKind: "enyo.TableRow" +}); + +/** + _enyo.TableRow_ implements an HTML <tr> element. +*/ +enyo.kind({ + name: "enyo.TableRow", + tag: "tr", + defaultKind: "enyo.TableCell" +}); + +/** + _enyo.TableCell_ implements an HTML <td> element. +*/ +enyo.kind({ + name: "enyo.TableCell", + tag: "td" +}); \ No newline at end of file diff --git a/enyo/source/ui/TextArea.js b/enyo/source/ui/TextArea.js new file mode 100644 index 0000000..72e3aaa --- /dev/null +++ b/enyo/source/ui/TextArea.js @@ -0,0 +1,20 @@ +/** + _enyo.TextArea_ implements an HTML <textarea> element with + cross-platform support for change events. + + For more information, see the documentation on + [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.TextArea", + kind: enyo.Input, + //* @protected + tag: "textarea", + classes: "enyo-textarea", + // textarea does use value attribute; needs to be kicked when rendered. + rendered: function() { + this.inherited(arguments); + this.valueChanged(); + } +}); diff --git a/enyo/source/ui/ToolDecorator.js b/enyo/source/ui/ToolDecorator.js new file mode 100644 index 0000000..6ea806a --- /dev/null +++ b/enyo/source/ui/ToolDecorator.js @@ -0,0 +1,9 @@ +/** + _enyo.ToolDecorator_ lines up components in a row, centered vertically. +*/ +enyo.kind({ + name: "enyo.ToolDecorator", + //* @protected + kind: enyo.GroupItem, + classes: "enyo-tool-decorator" +}); diff --git a/enyo/source/ui/package.js b/enyo/source/ui/package.js new file mode 100644 index 0000000..d1d78fa --- /dev/null +++ b/enyo/source/ui/package.js @@ -0,0 +1,21 @@ +enyo.depends( + "ui.css", + "Animator.js", + "BaseLayout.js", + "Image.js", + "Input.js", + "RichText.js", + "TextArea.js", + "Select.js", + "Group.js", + "GroupItem.js", + "ToolDecorator.js", + "Button.js", + "Checkbox.js", + "Repeater.js", + "DragAvatar.js", + "FloatingLayer.js", + "Popup.js", + "Selection.js", + "Table.js" +); diff --git a/enyo/source/ui/ui.css b/enyo/source/ui/ui.css new file mode 100644 index 0000000..0c60e9a --- /dev/null +++ b/enyo/source/ui/ui.css @@ -0,0 +1,26 @@ +.enyo-inline, .enyo-tool-decorator { + display: inline-block; +} + +.enyo-children-inline > *, .enyo-tool-decorator > * { + display: inline-block; +} + +.enyo-children-middle > *, .enyo-tool-decorator > * { + vertical-align: middle; +} + +.enyo-positioned { + position: relative; +} + +.enyo-fill { + position: relative; + width: 100%; + height: 100%; +} + +.enyo-popup { + position: absolute; + z-index: 10; +} \ No newline at end of file diff --git a/enyo/tools/README.md b/enyo/tools/README.md new file mode 100644 index 0000000..57c3c56 --- /dev/null +++ b/enyo/tools/README.md @@ -0,0 +1,23 @@ +# Enyo Minifier + +The enyo minifier uses Node.js, [UglifyJS](http://github.com/mishoo/uglifyjs) and the enyo dependency loader to compress any enyo package into a minimized form. + +## Invocation +For convenience, there are both Windows and Unix versions of the script that invokes the node tool. +They follow the same invocation: + + path/to/enyo/tools/minify/minify.sh package.js -output /relative/path/to/build/dir/buildfilename + +An example for lib/onyx, a UI widget set, run from `lib/onyx/minify/minify.sh`, building to `lib/onyx/build` + + ../../../enyo/tools/minify/minify.sh -output ../build/onyx package.js + +The last parameter in the output path, if not ending in a `/`, will be used as the name of the output build files. +The `package.js` file must be in the same directory as the invocation. + +For convenience, packages should include a `minify` folder with both a Windows batch and Unix shell script that runs the minifier. + +## Running tests +1. You first need to install an http server handling php (MANP or WAMP, ...) +2. Configure your http server to serve the files of the enyo project +3. Point your browser to enyo/tools/... to run the various testcases \ No newline at end of file diff --git a/enyo/tools/deploy.js b/enyo/tools/deploy.js new file mode 100644 index 0000000..5d8d44a --- /dev/null +++ b/enyo/tools/deploy.js @@ -0,0 +1,230 @@ +#!/usr/bin/env node + +/** +# deploy.js - portable deployment script + +This portable Node.js script minifies both your application, its +libraries & the Enyo framework it is using. The resulting application +is suitable for production usage, either hostet on a web-server or +embedded into a PhoneGap container. + +The script is intended to be run from the application's root directory +(This is unlike previous deprecated incarnations of the scripts +`deploy.sh` and `deploy.bat` that shipped within the `bootplate` +application), where it expects to find a file called `package.js` +(unless the user specifies an alternate location using the `-p` flag). + +This script comes along with Enyo. It automatically uses & embeds the +Enyo version it is shipped with, unless the user specifies another +Enyo version using the `-e enyo_dir` flag. + +When you application has library dependencies (for example +`lib/mylib`), this script uses the `lib/mylib/manifest.json` (if +present) or the old-fashioned deployment scripts `lib/mylib/deploy.sh` +(on Linux & Mac OSX) or `lib/mylib/deploy.bat` (on Windows). +If neither exist, then the entire library is copied (except for .git dir). + +This script also expects to find the following files & folders in the +application root directory. Each of them is copied verbatim in the +output production/deployment folder (the one optionally given using +the `-o` flag). + +* `index.html`, the application startup page +* `icon.png`, the application icon +* `assets/`holds the static application assets, such as images, + videos... etc. + + */ + +// Load dependencies + +var nopt = require("nopt"), + path = require('path'), + fs = require('fs'), + util = require('util'), + shell = require('shelljs'); + +var stat, ppwd, lib, script, scripts = {}; + +// Send message to parent node process, if any +process.on('uncaughtException', function (err) { + var errMsg = err.toString() + err.stack; + console.error(errMsg); + if (process.send) { + // only available if parent process is node + process.send({error: errMsg}); + } + process.exit(1); +}); +// receive error messages from child node processes +process.on('message', function(msg) { + console.dir(basename, msg); + if (msg.error && msg.error.stack) { + console.error(basename, msg.error.stack); + } + if (process.send) { + process.send(msg); + } +}); + +// Parse arguments + +var node = process.argv[0], + deploy = process.argv[1], + sourceDir = process.cwd(), + packageJs = path.resolve(sourceDir, "package.js"), + enyoDir = path.resolve(__dirname, '..'), + buildDir = path.resolve(sourceDir, "build"), + name = path.basename(sourceDir), + outDir = path.resolve(sourceDir, 'deploy', name), + less = true, // LESS compilation, turned on by default + verbose = false; + +function printUsage() { + // format generated using node-optimist... + console.log('\n' + + 'Usage: ' + node + ' ' + deploy + ' [-c][-e enyo_dir][-b build_dir][-o out_dir][-p package_js][-s source_dir]\n' + + '\n' + + 'Options:\n' + + ' -v verbose operation [boolean] [default: ' + verbose + ']\n' + + ' -b alternate build directory [default: "' + buildDir + '"]\n' + + ' -c do not run the LESS compiler [boolean] [default: ' + less + ']\n' + + ' -e location of the enyo framework [default: "' + enyoDir + '"]\n' + + ' -o alternate output directory [default: "' + outDir + '"]\n' + + ' -p location of the main package.js file [default: "' + packageJs + '"]\n' + + ' -s source code root directory [default: "' + sourceDir + '"]\n' + + '\n'); +} + +var opt = nopt(/*knownOpts*/ { + "build": path, + "less": Boolean, + "enyo": path, + "out": path, + "packagejs": path, + "source": path, + "verbose": Boolean, + "help": Boolean +}, /*shortHands*/ { + "b": "--build", + "c": "--no-less", + "e": "--enyo", + "o": "--out", + "p": "--packagejs", + "s": "--source", + "v": "--verbose", + "h": "--help", + "?": "--help" +}, process.argv /*args*/, 2 /*slice*/); + +if (opt.help) { + printUsage(); + process.exit(1); +} + +// nopt has not default values system +buildDir = opt.build || buildDir; +enyoDir = opt.enyo || enyoDir; +outDir = opt.out || outDir; +packageJs = opt.packagejs || + (opt.source ? path.join(opt.source, 'package.js') : undefined) || + packageJs; +sourceDir = opt.source || + (opt.packagejs ? path.dirname(opt.packagejs) : undefined) || + sourceDir; +less = (opt.less !== false) && less; +verbose = opt.verbose; + +var minifier = path.resolve(enyoDir, 'tools', 'minifier', 'minify.js'); +if (verbose) console.log("Using: build_dir=" + buildDir); +if (verbose) console.log("Using: enyo_dir=" + enyoDir); +if (verbose) console.log("Using: out_dir=" + outDir); +if (verbose) console.log("Using: packagejs=" + packageJs); +if (verbose) console.log("Using: source_dir=" + sourceDir); +if (verbose) console.log("Using: less=" + less); + +// utils + +function run(args) { + var command = '"' + args.join('" "') + '"'; + var report; + if (verbose) console.log("Running: '", command, "' from '", process.cwd(), "'"); + report = shell.exec(command, { silent: true }); + if (report.code !== 0) { + throw new Error("Fail: '" + command + "'\n" + report.output); + } +} + +// Prepare target directory + +shell.rm('-rf', path.resolve(outDir)); +shell.rm('-rf', path.resolve(outDir)); +shell.mkdir('-p', path.join(outDir)); + +// Build / Minify + +console.log("Minify-ing Enyo..."); +process.chdir(path.resolve(enyoDir, 'minify')); +run([node, minifier, + '-no-alias', + '-enyo', enyoDir, + // XXX generates $buildDir/enyo.(js|css)' so this is + // XXX rather an 'output_prefix' than an 'out_dir'... + '-output', path.join(buildDir, 'enyo'), + 'package.js']); + +console.log("Minify-ing the application..."); +process.chdir(path.dirname(packageJs)); +run([node, minifier, + '-enyo', enyoDir, + '-output', path.join(buildDir, 'app'), + (less ? '-less' : '-no-less'), + 'package.js']); +process.chdir(sourceDir); + +// Deploy / Copy + +shell.mkdir('-p', path.join(outDir, 'lib')); +shell.cp(path.join(sourceDir, 'index.html'), path.join(sourceDir, 'icon.png'), outDir); +shell.cp('-r', buildDir, outDir); + +var assetsSrcDir = path.join(sourceDir, 'assets'); +if(shell.test('-d', assetsSrcDir)) { + shell.cp('-r', assetsSrcDir, outDir); +} + +var libSrcDir = path.join(sourceDir, 'lib'); +if(shell.test('-d', libSrcDir)) { + shell.ls(libSrcDir).forEach(deployLib); +} + +function deployLib(lib) { + var libOutdir = path.join(outDir, 'lib', lib); + // load & execute sub-'deploy.js' + try { + script = path.join(sourceDir, 'lib', lib, 'deploy.js'); + stat = fs.statSync(script); + if (!stat.isFile()) + throw new Error("*** Not a file: '" + script + "'"); + scripts[lib] = require(script); + scripts[lib].deploy(libOutdir); + } catch(e) { + // backward compatibility: run deploy.sh or deploy.bat + try { + script = path.join(sourceDir, 'lib', lib, 'deploy.' + (process.platform === 'win32' ? 'bat' : 'sh')); + stat = fs.statSync(script); + if (!stat.isFile()) + throw new Error("*** Not a file: '" + script + "'"); + run([script, libOutdir]); + } catch(e2) { + // no deploy.(js|bat|sh): copy everything (then remove ".git", if any) + shell.cp('-r', path.join(sourceDir, 'lib', lib), path.join(outDir, 'lib')); + shell.rm('-rf', path.join(outDir, 'lib', lib, '.git')); + } + } +} + +console.log("Success: the deployable application is available in: ", outDir); +process.exit(0); + + diff --git a/enyo/tools/lessc.bat b/enyo/tools/lessc.bat new file mode 100644 index 0000000..a3b21e0 --- /dev/null +++ b/enyo/tools/lessc.bat @@ -0,0 +1,17 @@ +REM don't watch the sausage being made +@ECHO OFF + +REM the folder this script is in (*/enyo/tools) +SET TOOLS=%~DP0 + +REM enyo location +SET ENYO=%TOOLS%\.. + +REM lessc script location +SET LESSC=%TOOLS%\minifier\lessc.js + +REM node location +SET NODE=node.exe + +REM use node to invoke lessc with a known path to enyo and imported parameters +%NODE% "%LESSC%" -enyo "%ENYO%" %* diff --git a/enyo/tools/lessc.sh b/enyo/tools/lessc.sh new file mode 100644 index 0000000..9390758 --- /dev/null +++ b/enyo/tools/lessc.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# the folder this script is in (*/enyo/tools) +TOOLS="$(cd `dirname $0`; pwd)" +# enyo location +ENYO="$TOOLS/.." +# lessc script location +LESSC="$TOOLS/minifier/lessc.js" + +# check for node, but quietly +if command -v node >/dev/null 2>&1; then + # use node to invoke minify with a known path to enyo and imported parameters + echo "enyo/tools/lessc.sh args: " $@ + node "$LESSC" -enyo "$ENYO" $@ +else + echo "No node found in path" + exit 1 +fi diff --git a/enyo/tools/minifier/lessc.js b/enyo/tools/minifier/lessc.js new file mode 100644 index 0000000..e329f0a --- /dev/null +++ b/enyo/tools/minifier/lessc.js @@ -0,0 +1,80 @@ +var + fs = require("fs"), + path = require("path"), + walker = require("walker"), + jsp = require("uglify-js").parser, + pro = require("uglify-js").uglify, + nopt = require("nopt"), + less = require("less") + ; + +// Shimming path.relative with 0.8.8's version if it doesn't exist +if(!path.relative){ + path.relative = require('./path-relative-shim').relative; +} + +function printUsage() { + w("Enyo Less->CSS Compiler"); + w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)"); + w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory"); + w("-h, -?, -help:", "Show this message"); +} + +function finish(loader) { + for (var i=0, sheet; (sheet=loader.sheets[i]); i++) { + if (sheet.slice(-5) == ".less") { + w(sheet); + var code = fs.readFileSync(sheet, "utf8"); + var parser = new(less.Parser)({filename:sheet, paths:[path.dirname(sheet)]}); + var cssFile = sheet.slice(0,sheet.length-5) + ".css"; + parser.parse(code, function (err, tree) { + if (err) { + console.error(err); + } else { + var css = + "/* WARNING: This is a generated file for backward-compatibility. Most */\n" + + "/* usrs should instead modify LESS files. If you choose to edit this CSS */\n" + + "/* directly rather than LESS files, you should make sure less.xx.yy.min.js */\n" + + "/* is commented out in your debug.html, and run deploy.sh/bat using the */\n" + + "/* '-c' flag to disable LESS compilation. This will force the loader and */\n" + + "/* minifier to fall back to using CSS files in place of the same-name */\n" + + "/* LESS file. */\n" + + "\n" + tree.toCSS() + fs.writeFileSync(cssFile, css, "utf8"); + } + }); + } + } +} + +w = console.log; + +var knownOpts = { + "enyo": String, + "output": String, + "help": Boolean +}; + +var shortHands = { + "enyo": ['--enyo'], + "output": ['--output'], + "h": ['--help'], + "?": ['--help'], + "help": ['--help'] +}; + +opt = nopt(knownOpts, shortHands, process.argv, 2); +opt.source = opt.argv.remain[0]; +//w(opt); +//w(""); + +w(""); + +if (opt.help) { + printUsage(); + process.exit(); +} + +walker.init(opt.enyo); +walker.walk(opt.source, finish); + diff --git a/enyo/tools/minifier/minify.js b/enyo/tools/minifier/minify.js new file mode 100644 index 0000000..dd521db --- /dev/null +++ b/enyo/tools/minifier/minify.js @@ -0,0 +1,231 @@ +var + fs = require("fs"), + path = require("path"), + walker = require("walker"), + jsp = require("uglify-js").parser, + pro = require("uglify-js").uglify, + nopt = require("nopt"), + less = require("less") + ; + +var basename = path.basename(__filename), + w = console.log, + e = console.error; + +// Shimming path.relative with 0.8.8's version if it doesn't exist +if(!path.relative){ + path.relative = require('./path-relative-shim').relative; +} + +function printUsage() { + w("Enyo 2.0 Minifier"); + w("Flags:"); + w("-no-less:", "Don't compile less; instad substitute css for less"); + w("-no-alias:", "Don't use path macros"); + w("-alias:", "Give paths a macroized alias"); + w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)"); + w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory"); + w("-h, -?, -help:", "Show this message"); +} + +// properly split path based on platform +function pathSplit(inPath) { + var sep = process.platform == "win32" ? "\\" : "/"; + return inPath.split(sep); +} + +buildPathBlock = function(loader) { + var p$ = []; + for (var i=0, p; (p=loader.packages[i]); i++) { + if (p.name.indexOf("-") == -1) { + p$.push(p.name + ': "' + p.folder + '"'); + } + } + p = p$.join(', '); + return !p ? "" : "\n// minifier: path aliases\n\nenyo.path.addPaths({" + p + "});\n"; +}; + +concatCss = function(loader, doneCB) { + w(""); + var blob = ""; + var addToBlob = function(sheet, code) { + // fix url paths + code = code.replace(/url\([^)]*\)/g, function(inMatch) { + // find the url path, ignore quotes in url string + var matches = /url\s*\(\s*(('([^']*)')|("([^"]*)")|([^'"]*))\s*\)/.exec(inMatch); + var urlPath = matches[3] || matches[5] || matches[6]; + // skip data urls + if (/^data:/.test(urlPath)) { + return "url(" + urlPath + ")"; + } + // skip an external link + if (/^http(:?s)?:/.test(urlPath)) { + return "url(" + urlPath + ")"; + } + // get absolute path to referenced asset + var normalizedUrlPath = path.join(sheet, "..", urlPath); + // Make relative asset path to built css + var relPath = path.relative(path.dirname(opt.output || "build"), normalizedUrlPath); + if (process.platform == "win32") { + relPath = pathSplit(relPath).join("/"); + } + return "url(" + relPath + ")"; + }); + blob += "\n/* " + sheet + " */\n\n" + code + "\n"; + } + // Pops one sheet off the sheets[] array, reads (and parses if less), and then + // recurses again from the async callback until no sheets left, then calls doneCB + var readAndParse = function(sheets) { + var sheet = sheets.shift(); + if (sheet) { + w(sheet); + var isLess = (sheet.slice(-4) == "less"); + if (isLess && (opt.less !== true)) { + sheet = sheet.slice(0, sheet.length-4) + "css"; + isLess = false; + w(" (Substituting CSS: " + sheet + ")"); + } + var code = fs.readFileSync(sheet, "utf8"); + if (isLess) { + var parser = new(less.Parser)({filename:sheet, paths:[path.dirname(sheet)]}); + parser.parse(code, function (err, tree) { + if (err) { + console.error(err); + } else { + addToBlob(sheet, tree.toCSS()); + } + readAndParse(sheets); + }); + } else { + addToBlob(sheet, code); + readAndParse(sheets); + } + } else { + doneCB(blob); + } + } + readAndParse(loader.sheets); +}; + +concatJs = function(loader) { + w(""); + var blob = ""; + for (var i=0, m; (m=loader.modules[i]); i++) { + if (typeof opt.alias === 'undefined' || opt.alias) { + w("* inserting path aliases"); + blob += buildPathBlock(loader); + opt.alias = false; + } + w(m.path); + blob += "\n// " + m.rawPath + "\n\n" + compressJsFile(m.path) + "\n"; + if (opt.alias == m.rawPath) { + w("* inserting path aliases"); + blob += buildPathBlock(loader); + } + } + return blob; +}; + +compress = function(inCode) { + var ast = jsp.parse(inCode); // parse code and get the initial AST + ast = pro.ast_mangle(ast); // get a new AST with mangled names + ast = pro.ast_squeeze(ast); // get an AST with compression optimizations + return pro.gen_code(ast, {indent_level:0, beautify: !opt.aggro, ascii_only:true}); // compressed code here +}; + +compressJsFile = function(inPath) { + var code = fs.readFileSync(inPath, "utf8"); + return compress(code); +}; + +finish = function(loader) { + //w(loader.packages); + //w(''); + // + var output = opt.output || "build"; + var outfolder = path.dirname(output); + var exists = fs.existsSync || path.existsSync; + if (outfolder != "." && !exists(outfolder)) { + fs.mkdirSync(outfolder); + } + // Unfortunately, less parsing is asynchronous, so concatCSS is now as well + concatCss(loader, function(css) { + if (css.length) { + w(""); + fs.writeFileSync(output + ".css", css, "utf8"); + } + // + var js = concatJs(loader); + /* + if (css.length) { + js += "\n// " + "minifier: load css" + "\n\n"; + js += 'enyo.machine.sheet("' + output + '.css");\n'; + } + */ + if (js.length) { + w(""); + fs.writeFileSync(output + ".js", js, "utf8"); + } + // + w(""); + w("done."); + w(""); + + // required to properly terminate a + // node.process.fork() call, as defined by + // + process.exit(0); + }); +}; + +var knownOpts = { + "alias": Boolean, + "enyo": String, + "output": String, + "help": Boolean +}; + +var shortHands = { + "alias": ['--alias'], + "enyo": ['--enyo'], + "output": ['--output'], + "h": ['--help'], + "?": ['--help'], + "help": ['--help'] +}; + +opt = nopt(knownOpts, shortHands, process.argv, 2); +opt.source = opt.argv.remain[0]; +w(opt); +w(""); + +w(""); + +if (opt.help) { + printUsage(); + process.exit(); +} + +// Send message to parent node process, if any +process.on('uncaughtException', function (err) { + e(err.stack); + if (process.send) { + // only available if parent-process is node + process.send({error: err}); + } + process.exit(1); +}); +// receive error messages from child node processes +process.on('message', function(msg) { + console.dir(basename, msg); + if (msg.error && msg.error.stack) { + console.error(basename, msg.error.stack); + } + if (process.send) { + process.send(msg); + } +}); + +walker.init(opt.enyo); +walker.walk(opt.source, finish); + diff --git a/enyo/tools/minifier/node_modules/less/CHANGELOG.md b/enyo/tools/minifier/node_modules/less/CHANGELOG.md new file mode 100644 index 0000000..1c763f8 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/CHANGELOG.md @@ -0,0 +1,49 @@ +# 1.3.0 + +2012-03-10 + +- @media bubbling +- Support arbitrary entities as selectors +- [Variadic argument support](https://gist.github.com/1933613) +- Behaviour of zero-arity mixins has [changed](https://gist.github.com/1933613) +- Allow `@import` directives in any selector +- Media-query features can now be a variable +- Automatic merging of media-query conditions +- Fix global variable leaks +- Fix error message on wrong-arity call +- Fix an `@arguments` behaviour bug +- Fix `::` selector output +- Fix a bug when using @media with mixins + + +# 1.2.1 + +2012-01-15 + +- Fix imports in browser +- Improve error reporting in browser +- Fix Runtime error reports from imported files +- Fix `File not found` import error reporting + + +# 1.2.0 + +2012-01-07 + +- Mixin guards +- New function `percentage` +- New `color` function to parse hex color strings +- New type-checking stylesheet functions +- Fix Rhino support +- Fix bug in string arguments to mixin call +- Fix error reporting when index is 0 +- Fix browser support in WebKit and IE +- Fix string interpolation bug when var is empty +- Support `!important` after mixin calls +- Support vanilla @keyframes directive +- Support variables in certain css selectors, like `nth-child` +- Support @media and @import features properly +- Improve @import support with media features +- Improve error reports from imported files +- Improve function call error reporting +- Improve error-reporting \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/LICENSE b/enyo/tools/minifier/node_modules/less/LICENSE new file mode 100644 index 0000000..40f3b78 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/LICENSE @@ -0,0 +1,179 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright (c) 2009-2010 Alexis Sellier diff --git a/enyo/tools/minifier/node_modules/less/Makefile b/enyo/tools/minifier/node_modules/less/Makefile new file mode 100644 index 0000000..b30ad0a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/Makefile @@ -0,0 +1,76 @@ +# +# Run all tests +# +test: + node test/less-test.js + +# +# Run benchmark +# +benchmark: + node benchmark/less-benchmark.js + +# +# Build less.js +# +SRC = lib/less +HEADER = build/header.js +VERSION = `cat package.json | grep version \ + | grep -o '[0-9]\.[0-9]\.[0-9]\+'` +DIST = dist/less-${VERSION}.js +RHINO = dist/less-rhino-${VERSION}.js +DIST_MIN = dist/less-${VERSION}.min.js + +less: + @@mkdir -p dist + @@touch ${DIST} + @@cat ${HEADER} | sed s/@VERSION/${VERSION}/ > ${DIST} + @@echo "(function (window, undefined) {" >> ${DIST} + @@cat build/require.js\ + build/ecma-5.js\ + ${SRC}/parser.js\ + ${SRC}/functions.js\ + ${SRC}/colors.js\ + ${SRC}/tree/*.js\ + ${SRC}/tree.js\ + ${SRC}/browser.js\ + build/amd.js >> ${DIST} + @@echo "})(window);" >> ${DIST} + @@echo ${DIST} built. + +rhino: + @@mkdir -p dist + @@touch ${RHINO} + @@cat build/require-rhino.js\ + build/ecma-5.js\ + ${SRC}/parser.js\ + ${SRC}/functions.js\ + ${SRC}/colors.js\ + ${SRC}/tree/*.js\ + ${SRC}/tree.js\ + ${SRC}/rhino.js > ${RHINO} + @@echo ${RHINO} built. + +min: less + @@echo minifying... + @@uglifyjs ${DIST} > ${DIST_MIN} + @@echo ${DIST_MIN} built. + +server: less + cp dist/less-${VERSION}.js test/html/ + cd test/html && python -m SimpleHTTPServer + +clean: + git rm dist/* + +dist: clean min + git add dist/* + git commit -a -m "(dist) build ${VERSION}" + git archive master --prefix=less/ -o less-${VERSION}.tar.gz + npm publish less-${VERSION}.tar.gz + +stable: + npm tag less ${VERSION} stable + + +.PHONY: test benchmark diff --git a/enyo/tools/minifier/node_modules/less/README.md b/enyo/tools/minifier/node_modules/less/README.md new file mode 100644 index 0000000..104c56c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/README.md @@ -0,0 +1,28 @@ +Note: The Enyo framework currently uses a [fork of Less](https://github.com/enyojs/less.js) with a minor change to [`lib/less/tree/url.js`](https://github.com/enyojs/less.js/blob/master/lib/less/tree/url.js) to ensure that URL paths are propertly rewritten relative to the file that defines the URL when running the node-based compiler used by Enyo's minifier (this is already the default behavior when compiling via the Less.js browser library). + +The `dist/less-1.3.0e.js` and `dist/less-1.3.0e.min.js` files are the browser library built from the head of the fork with the single url.js change above. + +There is an active conversation happening [here on github](https://github.com/cloudhead/less.js/pull/96) aimed at resolving the inconsistency between the browser and node compilers which the Enyo team is tracking, with the goal of moving back to the less.js master. + +=========== + +less.js +======= + +The **dynamic** stylesheet language. + + + +about +----- + +This is the JavaScript, and now official, stable version of LESS. + +For more information, visit . + +license +------- + +See `LICENSE` file. + +> Copyright (c) 2009-2011 Alexis Sellier diff --git a/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less b/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less new file mode 100644 index 0000000..bf7fef7 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less @@ -0,0 +1,3979 @@ +@bg: #f01; +@white: #fff; +@grey: #eee; +@black: #000; +@blue: #000; +@accent_colour: #000; +@light_grey: #eee; +@dark_grey: #eee; +@yellow: #422; +@red: #ff0000; +@colour_positive: #ff0000; +@colour_negative: #ff0000; + +.box_shadow (...) { +} +.text_shadow (...) { +} +.border_radius (...) { +} +.border_radius_top_left (...) { +} +.border_radius_top_right (...) { +} +.border_radius_bottom_right (...) { +} +.border_radius_bottom_left (...) { +} +.border_radius_top (...) { +} +.border_radius_right (...) { +} +.border_radius_bottom (...) { +} +.border_radius_left (...) { +} +div.browse { + margin: 0 0 20px; + &.class { + padding: 0; + } + div.header { + padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; + border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; + .border_radius_top(3); color: @light_grey; + h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + .active { + background: @white; color: @black; z-index: 4; + :hover { color: @black; } + } + :hover { color: @white; } + :first-child { .border_radius_left(2); } + :last-child { .border_radius_right(2); margin-right: 0; } + } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + :last-child { + a { border: none; } + } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > ul { + margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; + li { + display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; + background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); + a.remove { + position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; + .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; + img { vertical-align: middle; } + } + div.thumbnail { + .border_radius_top(3); position: relative; z-index: 3; + .marker { + position: absolute; padding: 2px; .border_radius(2); z-index: 3; + background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; + } + .marker.coupon { + height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; + b { + display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; + border-bottom: none; border-right: none; float: left; + } + span { + color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; + padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; + } + } + .marker.video { + position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; + b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } + } + .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } + a.thumbnail { + display: block; overflow: hidden; position: relative; text-align: center; + img { position: relative; display: block; margin: auto; } + } + } + div.text { + margin: 3px 0 0; display: block; + a { text-decoration: none; } + a.title { + display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; + white-space: nowrap; height: 16px; overflow: hidden; + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + small { + font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; + a { font-weight: bold; } + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + } + :hover { + background: @accent_colour; + a.remove { display: block; } + div.thumbnail { + a.marker.remove, a.marker.video { + b { display: inline-block; } + } + a.marker.video { .box_shadow(0, 0, 2, @black); } + } + div.text { + a { color: @white; } + a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + small { + color: @white * 0.75 + @accent_colour * 0.25; + :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + } + } + div.footer a { color: @white; } + } + } + > li.ad div.thumbnail a.thumbnail { + width: 130px; height: 97px; + img { width: 100%; height: 100%; } + } + > li.brand div.thumbnail a.thumbnail { + width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); + img { max-width: 120px; max-height: 87px; } + } + li.paginate { + margin-bottom: 0; + a { + display: block; position: relative; text-decoration: none; height: 131px; + div.arrow { + background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); + height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; + b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } + } + div.label { + position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; + color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; + font-weight: bold; font-size: 12px; text-align: center; + } + :hover { + div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } + } + } + :hover { background: transparent; } + } + li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } + li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } + } + > div.footer { + padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; + border-top: 1px solid @light_grey; .border_radius_bottom(3); + div.info { + float: left; color: @grey; + strong { color: @black; font-weight: normal; } + } + div.pagination { + float: right; + > * { + display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; + .border_radius(3); text-decoration: none; font-weight: bold; + font-size: 10px; text-transform: uppercase; + } + a { color: @grey; } + a:hover { color: @black; } + span.disabled { color: @light_grey; } + span.current { color: @white; background: @bg; border: none; } + span.current:hover { color: @white; } + } + } +} +div.browse.with_categories { margin: 0 0 0 160px; } +div.browse.with_options > ul { .border_radius_top(0); } +div.browse.with_footer > ul { .border_radius_bottom(0); } +/* Browse List */ +div.browse.list { +> ul { + margin: 0; min-height: 320px; + padding: 10px 0 0 10px; overflow: hidden; + > li { + display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; + .border_radius(3); position: relative; line-height: normal; + .marker { + position: absolute; padding: 2px; .border_radius(2); + background: url('/images/transparent_backgrounds/white_75.png'); + img { height: 12px; width: 12px; } + } + img.marker { height: 12px; width: 12px; } + span.marker.new { + color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; + font-weight: bold; + } + a.marker.media_type { + display: inline-block; text-decoration: none; top: 39px; left: 8px; + font-size: 10px; + b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } + img { vertical-align: middle; } + } + a.thumbnail { + float: left; + width: 68px; display: block; overflow: hidden; + border: 1px solid @light_grey; + :hover { border-color: @accent_colour; } + } + span.title_brand { + display: block; margin: 0 0 2px 75px; + a { margin: 0; display: inline; } + a.brand_name { font-weight: normal; font-size: 12px; } + } + a.ad_title { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + a.brand_name { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + small { + display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; + } + small.brand_name { display: inline; margin: 0; } + ul.chart { + margin: 0 0 0 80px; + height: 39px; + } + ul.networks { + margin: 3px 0 0 75px; padding: 0; overflow: hidden; + li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } + } + div.points { + display: none; + font-size: 12px; text-align: right; + label { color: @grey; } + } + a.remove { bottom: -3px; right: -3px; } + } + li.ad { + a.thumbnail { height: 51px; } + span.title_brand { + small.brand_name { + display: block; + } + } + } + li.brand { + a.thumbnail { height: 68px; } + } + } +} +div.browse.list.with_options ul { .border_radius_top(0); } +div.browse.list.with_footer ul { .border_radius_bottom(0); } +div.browse.list.cols_2 { + > ul { + > li { + width: 285px; float: left; + :hover { + background: @white; + } + } + } +} +div.browse.ads.list { + > ul { + > li { + height: 53px; + a.thumbnail { + height: 51px; + } + } + } +} +div.browse.brands.list { + > ul { + > li { + height: 68px; + a.thumbnail { + height: 66px; + } + } + } +} + +/* Categories List */ +#categories { + margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; + ul { + margin: 0; padding: 10px 0 0; + li { + list-style: none; margin: 0; padding: 0; font-size: 14px; + a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } + a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } + } + .all a { font-weight: bold; } + .current a { + background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; + padding-left: 10px; + } + } +} + +/* Ads > Show */ +#ad { + div.header { + overflow: hidden; + h3 { font-size: 16px; margin: 0 0 3px; } + small { + a.category { font-weight: bold; color: @accent_colour; } + span.networks img { position: relative; top: 3px; } + } + span.brand { + float: right; color: @white; + a.brand_name { font-weight: bold; color: @accent_colour; } + } + } + div.content { + padding: 0; position: relative; + a.toggle_size { + display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; + background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; + position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; + } + img.creative { margin: 0 auto; max-width: 540px; display: block; } + object { position: relative; z-index: 44; } + object.video { line-height: 0; font-size: 0; } + object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } + } + div.content.not_video { + padding: 40px; text-align: center; + * { margin-left: auto; margin-right: auto; } + object.flash { margin-bottom: 0; } + } + div.footer { + padding: 0; + div.vote_views { + padding: 5px 10px; overflow: hidden; + div.share { float: right; margin: 2px 0 0 0; } + #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } + } + } +} +#sidebar { + #meta { + table { + margin: 0; + tr:last-child td { padding-bottom: 0; } + td { + padding: 0 0 5px; + ul.networks { + margin: 0; padding: 0; + li { + list-style: none; display: inline; + } + li { + } + } + } + td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } + } + } +} + +/* Voting */ +div.voted { + font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; + img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } +} +#voted_up { + img { background: @colour_positive * 0.66 + @bg * 0.15; } +} +#voted_down { + img { background: @colour_negative * 0.66 + @bg * 0.15; } +} +#encourage_comment { + display: inline-block; line-height: 22px; font-weight: bold; +} +#vote { + overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; + a { + color: @white; font-weight: bold; overflow: hidden; display: block; + width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; + } + a.up { + float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); + :hover { background: @colour_positive * 0.85 + @bg * 0.15; } + } + a.down { + float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); + margin: 0 5px 0 1px; + :hover { background: @colour_negative * 0.85 + @bg * 0.15; } + } +} +#vote.disabled { + a.up { + background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } + a.down { + background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } +} + +/* Panels */ +div.panel { + margin: 0 0 20px; position: relative; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); .border_radius(3); + > div.header { + background: @bg url('/images/panel_header_bg.png') repeat-x top left; border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); + padding: 5px 10px 4px; .border_radius_top(3); min-height: 18px; + h2 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + h3 { color: @white; font-size: 14px; margin: 0; line-height: 18px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + small { display: block; font-size: 12px; color: @light_grey * 0.25 + @white * 0.75; } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + } + a:first-child { .border_radius_left(2); } + a:last-child { .border_radius_right(2); margin-right: 0; } + a.active { background: @white; color: @black; z-index: 4; } + a:hover { color: @white; } + a.active:hover { color: @black; } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + } + li:last-child { + a { border: none; } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > div.content { + background: @white; padding: 10px; + .no_padding { padding: 0; } + } + > div.footer { + background: @light_grey * 0.33 + @white * 0.66; border-top: 1px solid (@light_grey * 0.5 + @white * 0.5); + padding: 4px 10px 5px; .border_radius_bottom(3); + } +} +div.panel.no_footer div.content { .border_radius_bottom(3); } +div.panel.no_header div.content { .border_radius_top(3); } +div.panel.collapsable { + div.header { + cursor: pointer; + b.toggle { float: right; border: 5px solid transparent; border-bottom: 5px solid @white; border-top: none; display: block; width: 0; height: 0; margin: 6px 0 0 0; } + } + div.header:hover { + background-color: @bg * 0.75 + @white * 0.25; + } +} +div.panel.collapsed { + div.header { + border-bottom: none; .border_radius(3); + b.toggle { border-bottom: none; border-top: 5px solid @white; } + } + div.blank { border-bottom: none; .border_radius_bottom(3); } + div.content, div.footer { display: none; } +} + + +/* Sidebar Actions */ +#sidebar { + #actions { + .box_shadow(0, 0, 0, transparent); + div.content { + background: url('/images/transparent_backgrounds/accent_colour_10.png'); text-align: center; + p.endorsement { + margin: 0 0 10px; font-size: 14px; font-weight: bold; + small { font-weight: normal; line-height: inherit; margin: 10px 0 0; } + :last-child { margin: 0; } + } + div.share { margin: 5px 0 0; } + a.button { + font-size: 16px; line-height: normal; height: auto; padding: 5px 10px 5px 35px; font-weight: bold; margin: 0; position: relative; + img { position: absolute; top: 3px; left: 6px; } + } + div.flash.notice { + margin: 10px 0 0; font-size: 22px; + small { font-weight: normal; margin: 0 0 10px; } + } + div.flash.notice.done { margin: 0; } + small { + display: block; margin: 10px 0 0; font-size: 11px; color: #808080; line-height: 12px; + img.favicon { vertical-align: middle; } + } + div.blank { + border: none; background: none; padding: 10px 0 0; border-top: 1px solid (@accent_colour * 0.5 + @white * 0.5); + margin: 10px 0 0; + } + } + } +} + +/* People Lists */ +ul.people { + margin: 0; padding: 10px 0 0 10px; background: @white; + > li { + display: block; margin: 0 10px 10px 0; float: left; padding: 2px; width: 57px; position: relative; + .border_radius(2); background: @white; list-style: none; border: 1px solid (@light_grey * 0.33 + @white * 0.66); + a.avatar { + display: block; width: 59px; height: 59px; overflow: hidden; + img { width: 100%; height: 100%; } + } + a.name { display: block; font-size: 10px; text-align: center; } + :hover { + background: @accent_colour; + a.name { color: @white; } + } + } +} +ul.people.list { + padding: 0; + > li { + margin: 0 0 10px; padding: 0 0 10px; overflow: hidden; float: none; width: auto; .border_radius(0); + border: none; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); + span.points { + float: right; display: block; padding: 5px; background: @light_grey * 0.15 + @white * 0.85; line-height: 1; + text-align: center; width: 50px; height: 30px; .border_radius(3); margin: 0 0 0 10px; + strong { display: block; color: @black; font-size: 16px; margin: 2px 0 0; } + label { color: @grey; text-transform: uppercase; font-size: 10px; } + label.long { display: block; } + label.short { display: none; } + } + a.avatar { float: left; width: 40px; height: 40px; } + a.name { font-size: 14px; font-weight: bold; margin: 0 0 0 50px; text-align: left; } + a.name.long { display: inline; } + a.name.short { display: none; } + span.networks { + display: block; margin: 0 0 0 50px; + img.favicon { vertical-align: middle; } + } + :hover { + background: transparent; + a.name { color: @accent_colour * 0.85 + @black * 0.15; } + } + :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } + } +} +ul.people.list.small { + > li { + span.points { + padding: 3px 6px; height: 18px; font-size: 9px; line-height: 17px; width: 60px; + strong { font-size: 12px; margin: 0; display: inline; } + label { font-size: 9px; } + label.long { display: none; } + label.short { display: inline; } + } + a.avatar { width: 24px; height: 24px; } + a.name { display: inline; line-height: 24px; margin: 0 0 0 5px; font-size: 12px; height: 24px; } + a.name.long { display: none; } + a.name.short { display: inline; } + span.networks { display: inline; margin: 0; } + :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } + } +} +ul.people.tiled { + > li { + width: 28px; padding: 2px; + a.avatar { width: 24px; height: 24px; background: @white; padding: 2px; } + a.name, small, span.networks, span.points { display: none; } + } +} + +/* Comments */ +#comments { + ul { + margin: 0 0 20px; padding: 0; + li { + display: block; list-style: none; padding: 0; margin: 0 0 10px; + span.meta { + margin: 0; overflow: hidden; display: block; + small { font-size: 12px; color: @light_grey; float: right; line-height: 16px; display: inline-block; } + a.avatar { + display: inline-block; height: 16px; width: 16px; position: relative; top: 3px; + img { height: 100%; width: 100%; } + } + a.name { font-weight: bold; line-height: 16px; display: inline-block; } + span.inactive { color: @grey; font-weight: bold; line-height: 16px; display: inline-block; } + } + b.tail { + display: block; width: 0; height: 0; margin: 3px 0 0 10px; border: 5px solid transparent; border-top: none; + border-bottom: 5px solid @white; position: relative; z-index: 2; + } + blockquote { + margin: 0; padding: 10px; .border_radius(3); font-style: normal; background: @white; + color: @dark_grey; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); + } + } + } + form { + margin: 0; + textarea { width: 500px; } + } +} + +/* Sidebar Categories */ +#sidebar { + #categories { + margin: 0 0 20px; + width: auto; + p { margin: 0; } + } +} + +#sidebar { + #ads > ul li, #recommendations > ul li { + width: 81px; + div.thumbnail { + a.thumbnail { height: 60px; width: 81px; } + } + div.text { + a.title { font-size: 11px; height: 14px; line-height: 14px; } + small { display: none; } + } + } + #brands > ul li { + width: 55px; + div.thumbnail { + a.thumbnail { + height: 45px; width: 45px; + img { max-height: 45px; max-width: 45px; } + } + } + div.text { display: none; } + } +} + +/* My Account */ +#accounts_controller { + #top { + #page_title { + #page_options { + a.button.public_profile { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } + } + a.button.goto_dashboard { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } + } + } + } + } + #account_nav { + float: left; width: 200px; margin: 0 20px 0 0; + ul.nav { + margin: 0; padding: 0; + li { + margin: 0 0 5px; display: block; list-style: none; padding: 0; + a { + display: block; height: 30px; text-decoration: none; color: @white; + b { + border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; + height: 0; float: right; display: none; + } + span { + .border_radius(3); background: @bg; display: block; + line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; + } + } + :hover { + a { + color: @white; + b { border-left-color: @bg; display: block; } + span { background: @bg; .border_radius_right(0); } + } + } + } + li.current a { + b { border-left-color: @accent_colour; display: block; } + span { background: @accent_colour; color: @white; .border_radius_right(0); } + } + } + } + #main { + > div { + margin: 0 0 20px; + form { margin: 0; } + } + #profile { + a.avatar { + float: left; display: block; + width: 70px; overflow: hidden; position: relative; text-decoration: none; + img { width: 100%; } + span { + display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; + .border_radius(3); .text_shadow(1, 1, 0, @grey); + text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; + } + } + form { + margin: 0 0 0 90px; + h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } + ul.choices { + li { width: 30%; } + } + div.extra { margin-top: 20px; } + } + } + + #networks { + ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; + li:hover + { + background: @light_grey; display: block; float: left; width: 180px; + padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); + position: relative; + * { line-height: normal; } + img { vertical-align: middle; float: left; } + .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } + small { + font-size: 12px; color: @grey; display: block; margin-left: 42px; + strong { color: @black; font-weight: normal; } + } + :hover { + } + } + li.installed { + background: @white; + border: 2px solid @accent_colour; padding: 8px; + } + li.unavailable { + .name { color: @black; } + :hover { + background: @light_grey; + } + } + li:hover { + background: @light_grey * 0.5 + @white * 0.5; + } + } + } + } +} + +/* Shopping Style Panel */ +#shopping_style { + div.header a.button.small { float: right; } + div.content { + p { + margin: 0 0 10px; + label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } + span { color: @black; } + span.toggle { white-space: nowrap; color: @grey; } + :last-child { margin: 0; } + } + p.more { text-align: left; font-weight: normal; } + p.less { display: none; margin: 0; } + } +} + +/* People Controller */ +#people_controller.index { + #main { + div.panel { + float: left; width: 300px; margin: 0 20px 0 0; + :last-child { margin-right: 0; } + } + } +} +#people_controller.show { + #person_overview, #shopping_style { + a.button.small { + } + } + #content { + #shopping_style { + float: left; width: 240px; margin: 0 20px 0 0; + } + #main { width: 360px; } + } +} + +/* Search Results */ +#search_results { + margin: 0 0 20px; + li { + :hover { + small { color: @white * 0.75 + @accent_colour * 0.25; } + } + } +} +#search { + div.content { + padding: 20px; + form { + margin: 0; float: none; + span.submit_and_options { + display: block; + } + } + p { margin: 0 0 15px; } + h4 { font-weight: normal; margin: 0 0 5px; } + } +} + +/* Recommendations */ +#recommendations { + div.browse { + margin: 0; padding: 0; background: none; + ul { min-height: 0; .border_radius(0); } + } +} + +/* Blank States */ +div.blank { + padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; + border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; + h4 { font-size: 18px; margin: 0 0 10px; } + h4:last-child { margin: 0; } + p { font-size: 16px; margin: 0 0 10px; } + p:last-child { margin: 0; } + p.with_list_number.large { + span { margin-left: 48px; display: block; color: @white; } + } + p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } + a { white-space: nowrap; } + a.hide { + position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); + } +} + +div.blank.small { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 16px; } + p { margin: 0; } +} +div.blank.tiny { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 14px; } + p { margin: 0; font-size: 12px; } +} +div.blank.rounded { + .border_radius(3); margin: 0 0 20px; +} +div.blank.rounded.bottom { .border_radius_top(0); } +div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } +div.blank.no_border_top { border-top: none; } +div.blank.no_border_bottom { border-bottom: none; } +div.blank.no_side_borders { border-right: none; border-left: none; } +div.panel { + div.blank { + padding: 10px 20px; overflow: hidden; margin: 0; + h4 { font-weight: normal; font-size: 14px; } + p, ul { margin: 0 0 10px; font-size: 12px; } + p:last-child, ul:last-child { margin: 0; } + } +} + +/* Sidebar Browse */ +#sidebar { + div.panel { + div.content.browse { + padding: 0; margin: 0; + > ul { + min-height: 0; .border_radius(0); + > li { + div.thumbnail { + a.thumbnail { padding: 5px; } + img.marker.media_type { top: 48px; left: 8px; } + } + div.footer { + a.title, a.name { font-size: 11px; font-weight: normal; } + } + } + } + } + + div.content.browse.ads > ul > li { + width: 93px; + > div.thumbnail a.thumbnail { width: 83px; height: 62px; } + } + div.content.browse.brands { + .border_radius(3); + > ul { + background: none; + > li { + width: 52px; + > div.thumbnail { + padding: 3px; + a.thumbnail { width: 42px; height: 42px; padding: 2px; } + } + li.active { background: @accent_colour; } + } + } + } + div.footer { + div.info { float: none; } + div.pagination { float: none; margin: 3px 0 0; } + } + } +} + +/* List Numbers */ +label.list_number { + float: left; background: url('/images/transparent_backgrounds/black_15.png'); padding: 2px; width: 24px; height: 24px; display: block; + .border_radius(99); + b { + display: block; font-weight: bold; font-size: 14px; color: @white; background: @accent_colour; height: 20px; width: 20px; line-height: 20px; + text-align: center; .border_radius(99); .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); + border: 2px solid @white; + } +} +label.list_number.large { + padding: 4px; width: 48px; height: 48px; .border_radius(99); position: relative; left: -10px; + b { + font-size: 28px; height: 40px; width: 40px; .border_radius(99); line-height: 40px; + .text_shadow(2, 2, 0px, (@accent_colour * 0.75 + @black * 0.25)); border-width: 4px; + } +} + +/* Dashboard */ +#dashboard_controller { + #ads { + span.filter.state { float: right; } + } + #sidebar { + #shopping_style div.content { + p.less { display: block; } + p.more { display: none; } + } + #influences { + div.header { + padding-bottom: 0; + ul.tabs { + position: relative; top: 1px; z-index: 3; + li { + margin: 0 5px 0 0; + a { + border: none; background: url('/images/transparent_backgrounds/white_75.png'); + :hover { color: @black; } + } + } + li.active { + a { + background: @white; border: none; + :hover { color: @black; } + } + } + } + } + + div.tab_content { + overflow: hidden; padding: 0; + > ul { + padding: 10px 10px 0; max-height: 280px; min-height: 120px; overflow-y: scroll; .border_radius_bottom(3px); + } + } + div.footer { + form { + p { + margin: 0 0 5px; + img.marker { float: right; margin: 5px 0 0 0; } + span.invitee { + line-height: 26px; padding: 3px 3px 0; font-size: 14px; + small { color: @grey; font-size: 12px; } + } + } + p.indent { margin-left: 36px; } + p.submit { margin-top: 10px; } + } + } + } + } + + div.panel.full { + > div.content { + margin: 0; padding: 0; background: none; + ul { + li { + width: 148px; + div.thumbnail { + img.marker.media_type { top: 90px; } + a.thumbnail { width: 138px; height: 104px; } + } + } + } + } + } + #people { + form { + padding: 0 0 5px; + input { width: 225px; float: left; margin: 0 5px 0 0; } + a.button { height: 23px; line-height: 23px; width: 60px; padding: 0; text-align: center; } + } + } +} + +/* Remove Pages Titles when Browsing */ +#ads_controller, #brands_controller { + #page_title { display: none; } +} + +/* Brands > Show */ +#brands_controller.show { + #ads { + div.filters { + h3 { font-size: 16px; margin: 0; } + span.show { float: right; } + span.filter.dropdown.localisation { float: right; margin: 0 0 0 10px; } + span.filter.state { float: right; margin: 0 0 0 10px; } + } + } +} + +/* FAQ */ +#pages_controller.faq { + #answers { + h3 { margin-top: 20px; padding-top: 20px; border-top: 1px solid (@light_grey * 0.75 + @white * 0.25); } + h3.first { margin-top: 0; padding-top: 0; border: none; } + } + #questions { + div.content { + padding: 20px; + ul { + margin: 0; padding: 0; + li { + margin: 0 0 10px; list-style: none; display: block; padding: 0; + a { font-size: 14px; } + } + li:last-child { + margin: 0; + } + } + } + } +} + +/* Person Overview */ +#person_overview { + padding: 20px 10px; position: relative; z-index: 25; + #person { + float: left; width: 620px; + a.avatar { + display: block; float: left; width: 60px; height: 60px; + img { height: 100%; width: 100%; } + } + > div { + margin: 0 0 0 75px; color: @white; font-size: 14px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + } + div.name { + h2 { + margin: 0 0 5px; display: inline; + a { + font-size: 20px; font-weight: bold; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + line-height: 1; color: @white; text-decoration: none; + :hover { text-decoration: underline; } + } + a.button.small { + font-size: 10px; + :hover { text-decoration: none; } + } + } + + span.points { + float: right; display: block; padding: 5px 10px; .border_radius(2); text-align: center; background: @white; position: relative; + min-width: 45px; + strong { color: @black; font-weight: bold; font-size: 24px; line-height: 1; display: block; .text_shadow(0, 0, 0, transparent); } + label { font-size: 9px; text-transform: uppercase; color: @grey; display: block; .text_shadow(0, 0, 0, transparent); font-weight: bold; } + } + span.points.with_redeem { + .border_radius_bottom(0); + a.button { + display: block; text-align: center; .border_radius_top(0); font-size: 10px; font-weight: bold; padding: 0; + position: absolute; height: 18px; left: 0; right: 0; bottom: -19px; line-height: 18px; text-transform: uppercase; border: none; + } + } + div.options { margin: 0; } + } + div.meta { + color: @white * 0.66 + @bg * 0.33; + span { color: @white; } + label { color: @white * 0.66 + @bg * 0.33; } + ul.networks { + display: inline; margin: 0; padding: 0; + li { + display: inline; line-height: 1; + img { position: relative; vertical-align: middle; top: -1px; } + } + } + } + + div.extra { + font-size: 12px; margin-top: 20px; margin-bottom: 20px; + span.toggle { + .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + a { font-size: 10px; font-weight: bold; text-transform: uppercase; text-decoration: none; color: @accent_colour; } + b.arrow { display: inline-block; width: 0; height: 0; border: 5px solid transparent; position: relative; top: -2px; } + } + #less_info { + span.toggle { + b.arrow { border-top: 5px solid @accent_colour; border-bottom: 0; } + } + } + #more_info { + span.toggle { + float: right; + b.arrow { border-bottom: 5px solid @accent_colour; border-top: 0; } + } + h4 { + color: @white; margin: 0 0 10px 0; border-bottom: 1px solid (@white * 0.25 + @bg * 0.75); .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + span { font-size: 12px; } + } + p { + margin: 0 0 5px; + label { display: block; float: left; width: 120px; color: @white * 0.66 + @bg * 0.33; } + span { display: block; margin: 0 0 0 130px; } + } + p:last-child { margin: 0; } + + } + } + div.login { + margin: 0 0 0 75px; + a.button { font-weight: bold; } + } + } +} + +/* Dashboard Nav */ +#dashboard_nav { + position: absolute; bottom: 0; left: 10px; margin: 0; padding: 0; overflow: hidden; + li { + display: block; float: left; margin: 0 5px 0 0; + a { + display: block; height: 28px; padding: 0 10px; line-height: 28px; .border_radius_top(2); + text-decoration: none; color: @white; background: url('/images/transparent_backgrounds/accent_colour_30.png'); font-size: 14px; + font-weight: bold; + :hover { background: url('/images/transparent_backgrounds/accent_colour_45.png'); } + } + } + li.active { + a { + background: @white; color: @black; + :hover { color: @black; } + } + } +} + +/* Dwellometer */ +#dwellometer { + z-index: 45; float: right; .box_shadow(0, 0, 0, transparent); margin: 0; + div.content { + text-align: center; position: relative; + object, object embed { position: relative; z-index: 46; line-height: 0; } + div.title { + position: absolute; bottom: 10px; left: 0; right: 0; z-index: 50; + img { width: 120px; display: block; margin: 0 auto; position: relative; left: -5px; } + } + } +} + +/* Activity Stream */ +#activity { + div.content { + ul.events { + padding: 0; margin: 0 0 -10px; + li { + margin: 0; padding: 10px 0; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); + list-style: none; overflow: hidden; + small.meta { + font-size: 12px; color: @light_grey; float: right; + } + a.button { float: right; margin: 0 0 10px 10px; } + a.avatar, a.logo, a.thumbnail { + height: 32px; display: block; float: left; + img { width: 100%; height: 100%; } + } + a.avatar, a.logo, a.icon { width: 32px; } + a.thumbnail { width: 42px; } + div.symbols { + float: left; overflow: hidden; + b { + display: block; float: left; margin: 10px 5px 0; + img { height: 12px; width: 12px; } + } + b.voted { margin: 10px 3px 0; padding: 2px; .border_radius(2); } + b.voted.for { background: @colour_positive * 0.33 + @white * 0.66; } + b.voted.against { background: @colour_negative * 0.33 + @white * 0.66; } + } + /* Temporarily removed avatar and symbol */ +/* div.symbols a.agent, b { display: none; }*/ + div.description { + font-size: 12px; color: @grey; + a.agent { font-weight: bold; } + } + div.comment { + margin-top: 2px; + b.tail { + display: block; margin: 0 0 0 10px; width: 0; height: 0; border: 5px solid transparent; + border-top: none; border-bottom: 5px solid (@light_grey * 0.25 + @white * 0.75); + } + blockquote { + margin: 0; font-style: normal; color: @dark_grey; + .border_radius(3); background: @light_grey * 0.25 + @white * 0.75; padding: 5px 10px; + span.view_comment { + color: @grey; + } + } + } + div.content { + overflow: hidden; + } + } + li.new_comment.ad, li.endorsed.ad, li.voted { + div.description, div.content { margin-left: 106px; } +/* div.description, div.content { margin-left: 53px; }*/ + } + li.new_comment.brand, li.replied_to, li.endorsed.brand, li.connected, li.sn_setup { + div.description, div.content { margin-left: 96px; } +/* div.description, div.content { margin-left: 43px; }*/ + } + li.replied_to { + div.content { + a.thumbnail, a.logo { margin-top: 7px; } + } + } + li.replied_to.ad { + div.content { + div.comment { margin-left: 52px; } + } + } + li.replied_to.brand { + div.content { + div.comment { margin-left: 42px; } + } + } + li.voted div.description span.action { .border_radius(2); color: @dark_grey; padding: 0 3px; white-space: nowrap; } + li.voted.for div.description span.action { background: @colour_positive * 0.15 + @white * 0.85; } + li.voted.against div.description span.action { background: @colour_negative * 0.15 + @white * 0.85; } + li:first-child { padding-top: 0; } + li:last-child { border-bottom: none; } + li:hover div.content div.comment blockquote span.view_comment { + } + } + } +} + +/* Login/Register Modal */ +#login_register { + div.location_select, + div.location_search { margin-left: 130px; } + h3 { + small { font-size: 14px; font-weight: normal; display: block; color: @grey; text-align: left; margin: 0; display: block; } + } +} + +/* Contact Form in Pages */ +#pages_controller { + #sidebar { + #contact { + margin: 15px 0 0; + form { + label { text-align: left; float: none; width: auto; font-size: 12px; font-weight: bold; line-height: 1; margin: 0 0 5px; } + p.submit.indent { + margin: 0; + span.with_cancel { display: none; } + } + } + } + } +} + +/* Exclusive Offers */ +#offers { + div.content { + a.gift { + display: block; text-align: center; + img { height: 100px; } + } + } +} + +div.browse { + margin: 0 0 20px; + &.class { + padding: 0; + } + div.header { + padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; + border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; + .border_radius_top(3); color: @light_grey; + h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + .active { + background: @white; color: @black; z-index: 4; + :hover { color: @black; } + } + :hover { color: @white; } + :first-child { .border_radius_left(2); } + :last-child { .border_radius_right(2); margin-right: 0; } + } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + :last-child { + a { border: none; } + } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > ul { + margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; + li { + display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; + background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); + a.remove { + position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; + .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; + img { vertical-align: middle; } + } + div.thumbnail { + .border_radius_top(3); position: relative; z-index: 3; + .marker { + position: absolute; padding: 2px; .border_radius(2); z-index: 3; + background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; + } + .marker.coupon { + height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; + b { + display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; + border-bottom: none; border-right: none; float: left; + } + span { + color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; + padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; + } + } + .marker.video { + position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; + b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } + } + .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } + a.thumbnail { + display: block; overflow: hidden; position: relative; text-align: center; + img { position: relative; display: block; margin: auto; } + } + } + div.text { + margin: 3px 0 0; display: block; + a { text-decoration: none; } + a.title { + display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; + white-space: nowrap; height: 16px; overflow: hidden; + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + small { + font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; + a { font-weight: bold; } + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + } + :hover { + background: @accent_colour; + a.remove { display: block; } + div.thumbnail { + a.marker.remove, a.marker.video { + b { display: inline-block; } + } + a.marker.video { .box_shadow(0, 0, 2, @black); } + } + div.text { + a { color: @white; } + a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + small { + color: @white * 0.75 + @accent_colour * 0.25; + :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + } + } + div.footer a { color: @white; } + } + } + > li.ad div.thumbnail a.thumbnail { + width: 130px; height: 97px; + img { width: 100%; height: 100%; } + } + > li.brand div.thumbnail a.thumbnail { + width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); + img { max-width: 120px; max-height: 87px; } + } + li.paginate { + margin-bottom: 0; + a { + display: block; position: relative; text-decoration: none; height: 131px; + div.arrow { + background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); + height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; + b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } + } + div.label { + position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; + color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; + font-weight: bold; font-size: 12px; text-align: center; + } + :hover { + div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } + } + } + :hover { background: transparent; } + } + li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } + li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } + } + > div.footer { + padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; + border-top: 1px solid @light_grey; .border_radius_bottom(3); + div.info { + float: left; color: @grey; + strong { color: @black; font-weight: normal; } + } + div.pagination { + float: right; + > * { + display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; + .border_radius(3); text-decoration: none; font-weight: bold; + font-size: 10px; text-transform: uppercase; + } + a { color: @grey; } + a:hover { color: @black; } + span.disabled { color: @light_grey; } + span.current { color: @white; background: @bg; border: none; } + span.current:hover { color: @white; } + } + } +} +div.browse.with_categories { margin: 0 0 0 160px; } +div.browse.with_options > ul { .border_radius_top(0); } +div.browse.with_footer > ul { .border_radius_bottom(0); } +/* Browse List */ +div.browse.list { +> ul { + margin: 0; min-height: 320px; + padding: 10px 0 0 10px; overflow: hidden; + > li { + display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; + .border_radius(3); position: relative; line-height: normal; + .marker { + position: absolute; padding: 2px; .border_radius(2); + background: url('/images/transparent_backgrounds/white_75.png'); + img { height: 12px; width: 12px; } + } + img.marker { height: 12px; width: 12px; } + span.marker.new { + color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; + font-weight: bold; + } + a.marker.media_type { + display: inline-block; text-decoration: none; top: 39px; left: 8px; + font-size: 10px; + b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } + img { vertical-align: middle; } + } + a.thumbnail { + float: left; + width: 68px; display: block; overflow: hidden; + border: 1px solid @light_grey; + :hover { border-color: @accent_colour; } + } + span.title_brand { + display: block; margin: 0 0 2px 75px; + a { margin: 0; display: inline; } + a.brand_name { font-weight: normal; font-size: 12px; } + } + a.ad_title { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + a.brand_name { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + small { + display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; + } + small.brand_name { display: inline; margin: 0; } + ul.chart { + margin: 0 0 0 80px; + height: 39px; + } + ul.networks { + margin: 3px 0 0 75px; padding: 0; overflow: hidden; + li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } + } + div.points { + display: none; + font-size: 12px; text-align: right; + label { color: @grey; } + } + a.remove { bottom: -3px; right: -3px; } + } + li.ad { + a.thumbnail { height: 51px; } + span.title_brand { + small.brand_name { + display: block; + } + } + } + li.brand { + a.thumbnail { height: 68px; } + } + } +} +div.browse.list.with_options ul { .border_radius_top(0); } +div.browse.list.with_footer ul { .border_radius_bottom(0); } +div.browse.list.cols_2 { + > ul { + > li { + width: 285px; float: left; + :hover { + background: @white; + } + } + } +} +div.browse.ads.list { + > ul { + > li { + height: 53px; + a.thumbnail { + height: 51px; + } + } + } +} +div.browse.brands.list { + > ul { + > li { + height: 68px; + a.thumbnail { + height: 66px; + } + } + } +} + +/* Categories List */ +#categories { + margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; + ul { + margin: 0; padding: 10px 0 0; + li { + list-style: none; margin: 0; padding: 0; font-size: 14px; + a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } + a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } + } + .all a { font-weight: bold; } + .current a { + background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; + padding-left: 10px; + } + } +} + +/* Ads > Show */ +#ad { + div.header { + overflow: hidden; + h3 { font-size: 16px; margin: 0 0 3px; } + small { + a.category { font-weight: bold; color: @accent_colour; } + span.networks img { position: relative; top: 3px; } + } + span.brand { + float: right; color: @white; + a.brand_name { font-weight: bold; color: @accent_colour; } + } + } + div.content { + padding: 0; position: relative; + a.toggle_size { + display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; + background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; + position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; + } + img.creative { margin: 0 auto; max-width: 540px; display: block; } + object { position: relative; z-index: 44; } + object.video { line-height: 0; font-size: 0; } + object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } + } + div.content.not_video { + padding: 40px; text-align: center; + * { margin-left: auto; margin-right: auto; } + object.flash { margin-bottom: 0; } + } + div.footer { + padding: 0; + div.vote_views { + padding: 5px 10px; overflow: hidden; + div.share { float: right; margin: 2px 0 0 0; } + #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } + } + } +} +#sidebar { + #meta { + table { + margin: 0; + tr:last-child td { padding-bottom: 0; } + td { + padding: 0 0 5px; + ul.networks { + margin: 0; padding: 0; + li { + list-style: none; display: inline; + } + li { + } + } + } + td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } + } + } +} + +/* Voting */ +div.voted { + font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; + img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } +} +#voted_up { + img { background: @colour_positive * 0.66 + @bg * 0.15; } +} +#voted_down { + img { background: @colour_negative * 0.66 + @bg * 0.15; } +} +#encourage_comment { + display: inline-block; line-height: 22px; font-weight: bold; +} +#vote { + overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; + a { + color: @white; font-weight: bold; overflow: hidden; display: block; + width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; + } + a.up { + float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); + :hover { background: @colour_positive * 0.85 + @bg * 0.15; } + } + a.down { + float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); + margin: 0 5px 0 1px; + :hover { background: @colour_negative * 0.85 + @bg * 0.15; } + } +} +#vote.disabled { + a.up { + background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } + a.down { + background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } +} +#sidebar { + #ads > ul li, #recommendations > ul li { + width: 81px; + div.thumbnail { + a.thumbnail { height: 60px; width: 81px; } + } + div.text { + a.title { font-size: 11px; height: 14px; line-height: 14px; } + small { display: none; } + } + } + #brands > ul li { + width: 55px; + div.thumbnail { + a.thumbnail { + height: 45px; width: 45px; + img { max-height: 45px; max-width: 45px; } + } + } + div.text { display: none; } + } +} + +/* My Account */ +#accounts_controller { + #top { + #page_title { + #page_options { + a.button.public_profile { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } + } + a.button.goto_dashboard { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } + } + } + } + } + #account_nav { + float: left; width: 200px; margin: 0 20px 0 0; + ul.nav { + margin: 0; padding: 0; + li { + margin: 0 0 5px; display: block; list-style: none; padding: 0; + a { + display: block; height: 30px; text-decoration: none; color: @white; + b { + border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; + height: 0; float: right; display: none; + } + span { + .border_radius(3); background: @bg; display: block; + line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; + } + } + :hover { + a { + color: @white; + b { border-left-color: @bg; display: block; } + span { background: @bg; .border_radius_right(0); } + } + } + } + li.current a { + b { border-left-color: @accent_colour; display: block; } + span { background: @accent_colour; color: @white; .border_radius_right(0); } + } + } + } + #main { + > div { + margin: 0 0 20px; + form { margin: 0; } + } + #profile { + a.avatar { + float: left; display: block; + width: 70px; overflow: hidden; position: relative; text-decoration: none; + img { width: 100%; } + span { + display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; + .border_radius(3); .text_shadow(1, 1, 0, @grey); + text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; + } + } + form { + margin: 0 0 0 90px; + h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } + ul.choices { + li { width: 30%; } + } + div.extra { margin-top: 20px; } + } + } + + #networks { + ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; + li:hover + { + background: @light_grey; display: block; float: left; width: 180px; + padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); + position: relative; + * { line-height: normal; } + img { vertical-align: middle; float: left; } + .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } + small { + font-size: 12px; color: @grey; display: block; margin-left: 42px; + strong { color: @black; font-weight: normal; } + } + :hover { + } + } + li.installed { + background: @white; + border: 2px solid @accent_colour; padding: 8px; + } + li.unavailable { + .name { color: @black; } + :hover { + background: @light_grey; + } + } + li:hover { + background: @light_grey * 0.5 + @white * 0.5; + } + } + } + } +} + +/* Shopping Style Panel */ +#shopping_style { + div.header a.button.small { float: right; } + div.content { + p { + margin: 0 0 10px; + label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } + span { color: @black; } + span.toggle { white-space: nowrap; color: @grey; } + :last-child { margin: 0; } + } + p.more { text-align: left; font-weight: normal; } + p.less { display: none; margin: 0; } + } +} + +/* People Controller */ +#people_controller.index { + #main { + div.panel { + float: left; width: 300px; margin: 0 20px 0 0; + :last-child { margin-right: 0; } + } + } +} +#people_controller.show { + #person_overview, #shopping_style { + a.button.small { + } + } + #content { + #shopping_style { + float: left; width: 240px; margin: 0 20px 0 0; + } + #main { width: 360px; } + } +} + +/* Search Results */ +#search_results { + margin: 0 0 20px; + li { + :hover { + small { color: @white * 0.75 + @accent_colour * 0.25; } + } + } +} +#search { + div.content { + padding: 20px; + form { + margin: 0; float: none; + span.submit_and_options { + display: block; + } + } + p { margin: 0 0 15px; } + h4 { font-weight: normal; margin: 0 0 5px; } + } +} + +/* Recommendations */ +#recommendations { + div.browse { + margin: 0; padding: 0; background: none; + ul { min-height: 0; .border_radius(0); } + } +} + +/* Blank States */ +div.blank { + padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; + border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; + h4 { font-size: 18px; margin: 0 0 10px; } + h4:last-child { margin: 0; } + p { font-size: 16px; margin: 0 0 10px; } + p:last-child { margin: 0; } + p.with_list_number.large { + span { margin-left: 48px; display: block; color: @white; } + } + p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } + a { white-space: nowrap; } + a.hide { + position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); + } +} + +div.blank.small { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 16px; } + p { margin: 0; } +} +div.blank.tiny { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 14px; } + p { margin: 0; font-size: 12px; } +} +div.blank.rounded { + .border_radius(3); margin: 0 0 20px; +} +div.blank.rounded.bottom { .border_radius_top(0); } +div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } +div.blank.no_border_top { border-top: none; } +div.blank.no_border_bottom { border-bottom: none; } +div.blank.no_side_borders { border-right: none; border-left: none; } +div.panel { + div.blank { + padding: 10px 20px; overflow: hidden; margin: 0; + h4 { font-weight: normal; font-size: 14px; } + p, ul { margin: 0 0 10px; font-size: 12px; } + p:last-child, ul:last-child { margin: 0; } + } +} + +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: @r * 10; +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + .spacing { + height: 10px / 2px+6px-1px*2; + width: 2 * 4-5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6px * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width: (@var * @var) * 6; + height: (7 * 7) + (8 * 8); + margin: 4 * (5 + 5) / 2 - (@var * 2); + //margin: (6 * 6)px; +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2+3)*(2+3) / (9-4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} + +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +}h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; +} +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + font-family: @a, @a, @a; +} + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: @r * 10; +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + .spacing { + height: 10px / 2px+6px-1px*2; + width: 2 * 4-5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6px * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width: (@var * @var) * 6; + height: (7 * 7) + (8 * 8); + margin: 4 * (5 + 5) / 2 - (@var * 2); + //margin: (6 * 6)px; +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2+3)*(2+3) / (9-4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} + +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +}h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; +} +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + font-family: @a, @a, @a; +} + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} diff --git a/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js b/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js new file mode 100644 index 0000000..68fe1ad --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js @@ -0,0 +1,47 @@ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var less = require('../lib/less'); +var file = path.join(__dirname, 'benchmark.less'); + +if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) } + +fs.readFile(file, 'utf8', function (e, data) { + var tree, css, start, end, total; + + sys.puts("Benchmarking...\n", path.basename(file) + " (" + + parseInt(data.length / 1024) + " KB)", ""); + + start = new(Date); + + new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) { + end = new(Date); + + total = end - start; + + sys.puts("Parsing: " + + total + " ms (" + + parseInt(1000 / total * + data.length / 1024) + " KB\/s)"); + + start = new(Date); + css = tree.toCSS(); + end = new(Date); + + sys.puts("Generation: " + (end - start) + " ms (" + + parseInt(1000 / (end - start) * + data.length / 1024) + " KB\/s)"); + + total += end - start; + + sys.puts("Total: " + total + "ms (" + + parseInt(1000 / total * data.length / 1024) + " KB/s)"); + + if (err) { + less.writeError(err); + process.exit(3); + } + }); +}); + diff --git a/enyo/tools/minifier/node_modules/less/bin/lessc b/enyo/tools/minifier/node_modules/less/bin/lessc new file mode 100644 index 0000000..690535f --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/bin/lessc @@ -0,0 +1,160 @@ +#!/usr/bin/env node + +var path = require('path'), + fs = require('fs'), + sys = require('util'), + os = require('os'); + +var less = require('../lib/less'); +var args = process.argv.slice(1); +var options = { + compress: false, + yuicompress: false, + optimization: 1, + silent: false, + paths: [], + color: true, + strictImports: false +}; +var continueProcessing = true, + currentErrorcode; + +// calling process.exit does not flush stdout always +// so use this to set the exit code +process.on('exit', function() { process.reallyExit(currentErrorcode) }); + +args = args.filter(function (arg) { + var match; + + if (match = arg.match(/^-I(.+)$/)) { + options.paths.push(match[1]); + return false; + } + + if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] } + else { return arg } + + switch (arg) { + case 'v': + case 'version': + sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); + continueProcessing = false; + case 'verbose': + options.verbose = true; + break; + case 's': + case 'silent': + options.silent = true; + break; + case 'strict-imports': + options.strictImports = true; + break; + case 'h': + case 'help': + require('../lib/less/lessc_helper').printUsage(); + continueProcessing = false; + case 'x': + case 'compress': + options.compress = true; + break; + case 'yui-compress': + options.yuicompress = true; + break; + case 'no-color': + options.color = false; + break; + case 'include-path': + options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') + .map(function(p) { + if (p) { + return path.resolve(process.cwd(), p); + } + }); + break; + case 'O0': options.optimization = 0; break; + case 'O1': options.optimization = 1; break; + case 'O2': options.optimization = 2; break; + case 'line-numbers': + options.dumpLineNumbers = match[2]; + break; + } +}); + +if (!continueProcessing) { + return; +} + +var input = args[1]; +if (input && input != '-') { + input = path.resolve(process.cwd(), input); +} +var output = args[2]; +if (output) { + output = path.resolve(process.cwd(), output); +} + +if (! input) { + sys.puts("lessc: no input files"); + sys.puts(""); + require('../lib/less/lessc_helper').printUsage(); + currentErrorcode = 1; + return; +} + +var css, fd, tree; + +var parseLessFile = function (e, data) { + if (e) { + sys.puts("lessc: " + e.message); + currentErrorcode = 1; + return; + } + + new(less.Parser)({ + paths: [path.dirname(input)].concat(options.paths), + optimization: options.optimization, + filename: input, + strictImports: options.strictImports, + dumpLineNumbers: options.dumpLineNumbers + }).parse(data, function (err, tree) { + if (err) { + less.writeError(err, options); + currentErrorcode = 1; + return; + } else { + try { + css = tree.toCSS({ + compress: options.compress, + yuicompress: options.yuicompress + }); + if (output) { + fd = fs.openSync(output, "w"); + fs.writeSync(fd, css, 0, "utf8"); + fs.closeSync(fd); + } else { + sys.print(css); + } + } catch (e) { + less.writeError(e, options); + currentErrorcode = 2; + return; + } + } + }); +}; + +if (input != '-') { + fs.readFile(input, 'utf-8', parseLessFile); +} else { + process.stdin.resume(); + process.stdin.setEncoding('utf8'); + + var buffer = ''; + process.stdin.on('data', function(data) { + buffer += data; + }); + + process.stdin.on('end', function() { + parseLessFile(false, buffer); + }); +} diff --git a/enyo/tools/minifier/node_modules/less/build/amd.js b/enyo/tools/minifier/node_modules/less/build/amd.js new file mode 100644 index 0000000..c4b1187 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/build/amd.js @@ -0,0 +1,6 @@ +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define("less", [], function () { return less; } ); +} diff --git a/enyo/tools/minifier/node_modules/less/build/ecma-5.js b/enyo/tools/minifier/node_modules/less/build/ecma-5.js new file mode 100644 index 0000000..420bd88 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/build/ecma-5.js @@ -0,0 +1,120 @@ + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} diff --git a/enyo/tools/minifier/node_modules/less/build/header.js b/enyo/tools/minifier/node_modules/less/build/header.js new file mode 100644 index 0000000..c491d92 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/build/header.js @@ -0,0 +1,7 @@ +// +// LESS - Leaner CSS v@VERSION +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// diff --git a/enyo/tools/minifier/node_modules/less/build/require-rhino.js b/enyo/tools/minifier/node_modules/less/build/require-rhino.js new file mode 100644 index 0000000..02bc83c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/build/require-rhino.js @@ -0,0 +1,7 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + diff --git a/enyo/tools/minifier/node_modules/less/build/require.js b/enyo/tools/minifier/node_modules/less/build/require.js new file mode 100644 index 0000000..4d5b172 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/build/require.js @@ -0,0 +1,7 @@ +// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js new file mode 100644 index 0000000..487c06a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js @@ -0,0 +1,2695 @@ +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function (window, undefined) { +// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else { + return this.value[0].eval(env); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + toCSS: function () { + if (this.escaped) { + return this.evaluated; + } else { + return JSON.stringify(this.evaluated); + } + }, + eval: function (env) { + var result, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name).eval(env).value; + }); + + expression = new(Function)('return (' + expression + ')'); + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + this.evaluated = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + return this; + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(this.arguments, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + this.value = this.value.replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name).eval(env).value; + }).replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, this.index, true).eval(env).toCSS(); + }); + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js new file mode 100644 index 0000000..ede454e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value[0].eval(b)},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(this.arguments, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + this.value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name, that.index).eval(env).value; + }); + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js new file mode 100644 index 0000000..c204123 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree" +)),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js new file mode 100644 index 0000000..9b2fc8a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){ +if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js new file mode 100644 index 0000000..6e4d5cf --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this +.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^(?:\d*\.)?\d+%/); + + if (e) { return new(tree.Element)(c, e) } + + if (c.value && c.value[0] === '&') { + return new(tree.Element)(c, null); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#:% \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value[0] === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js new file mode 100644 index 0000000..182b526 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.4 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.4 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function s(a){return a&&a.parentNode.removeChild(a)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){t("browser doesn't support AJAX.");return null}}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function p(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||o(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(h){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function o(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function n(b,c,e,f){var h=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=g&&g.getItem(i),k=g&&g.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=h.slice(0,h.lastIndexOf("/")+1)+i),q(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())p(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return u(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),s(document.getElementById("less-error-message:"+o(i)))}catch(a){u(a,i)}})}catch(h){u(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function m(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/)||s(/^(?:\d*\.)?\d+%/);if(a)return new e.Element(c,a);if(c.value&&c.value[0]==="&")return new e.Element(c,null)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#:% \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs +.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (less.mode === 'browser' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + try { + style.innerHTML = css; + } catch (_) { + style.styleSheets.cssText = css; + } + style.type = 'text/css'; + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js new file mode 100644 index 0000000..49949fb --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.1.5 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function s(a){var d,e,g,h,i,m,n,o;if(a instanceof Function)return a.call(l.parsers);if(typeof a=="string")d=b.charAt(c)===a?a:null,g=1,r();else{r();if(d=a.exec(j[f]))g=d[0].length;else return null}if(d){o=c+=g,m=c+j[f].length-g;while(c0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)!=="/")return;if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=='"'&&b.charAt(d)!=="'")return;f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)},keyword:function(){var a;if(a=s(/^[_A-Za-z-][_A-Za-z0-9-]*/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!(a=/^([\w-]+|%)\(/.exec(j[f])))return;a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)!=="u"||!s(/^url\(/))return;a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(d>57||d<45||d===47)return;if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=="`")return;f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!t(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i!=="."&&i!=="#")return;while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d,c)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,d=[],f,g,h,i;if(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/))return;if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!s(/^\(opacity=/i))return;if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,d;d=s(this.combinator),a=s(/^(?:\d+\.\d+|\d+)%/)||s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(d,a,c);if(d.value&&d.value.charAt(0)==="&")return new e.Element(d,null,c)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!s("["))return;if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,f;p();while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g==="."||g==="#"||g==="&")return;if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)!=="@")return;if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-|-moz-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(a.value=b[0]+(a.value.charAt(0)==="/"?a.value.slice(1):a.value)),this.value=a,this.paths=b)},a.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(b){return this.attrs?this:new a.URL(this.value.eval(b),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k) + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/) || $('keyframes')) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + try { + style.innerHTML = css; + } catch (_) { + style.styleSheets.cssText = css; + } + style.type = 'text/css'; + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js new file mode 100644 index 0000000..a30623b --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.1.6 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),m=new e.Ruleset([],t(this.parsers.primary)),m.root=!0,m.toCSS=function(f){var g,h,i;return function(i,j){function p(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var k=[];i=i||{},typeof j=="object"&&!Array.isArray(j)&&(j=Object.keys(j).map(function(a){var b=j[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),k=[new e.Ruleset(null,j)]);try{var l=f.call(this,{frames:k}).toCSS([],{compress:i.compress||!1})}catch(m){h=b.split("\n"),g=p(m.index);for(var n=m.index,o=-1;n>=0&&b.charAt(n)!=="\n";n--)o++;throw{type:m.type,message:m.message,filename:a.filename,index:m.index,line:typeof g=="number"?g+1:null,callLine:m.call&&p(m.call)+1,callExtract:h[p(m.call)],stack:m.stack,column:o,extract:[h[g-1],h[g],h[g+1]]}}return i.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(l):i.compress?l.replace(/(\s)+/g,"$1"):l}}(m.eval);if(f=0&&b.charAt(x)!=="\n";x--)y++;w={name:"ParseError",message:"Syntax Error on line "+r,index:f,filename:a.filename,line:r,column:y,extract:[s[r-2],s[r-1],s[r]]}}this.imports.queue.length>0?o=function(){i(w,m)}:i(w,m)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var a,b,c=f;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;a=a[1].toLowerCase();if(a==="url")return null;f+=a.length;if(a==="alpha")return t(this.alpha);t("("),b=t(this.entities.arguments);if(!t(")"))return;if(a)return new e.Call(a,b,c)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!t(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=f;if(b.charAt(f)==="@"&&(a=t(/^@@?[\w-]+/)))return new e.Variable(a,c)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!u(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,g,h=f,i=b.charAt(f);if(i!=="."&&i!=="#")return;while(c=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(d,c,f)),d=t(">");t("(")&&(g=t(this.entities.arguments))&&t(")");if(a.length>0&&(t(";")||u("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,c=[],d,g,h,i;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||u(/^[^{]*(;|})/))return;if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)){if(h instanceof e.Variable)if(t(":"))if(i=t(this.expression))c.push({name:h.name,value:i});else throw new Error("Expected value");else c.push({name:h.name});else c.push({value:h});if(!t(","))break}if(!t(")"))throw new Error("Expected )");g=t(this.block);if(g)return new e.mixin.Definition(a,c,g)}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||u("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable)){if(!t(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/);if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}if(c===":"&&b.charAt(f+1)===":"){f+=2;while(b.charAt(f)===" ")f++;return new e.Combinator("::")}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var a=[],b,c,d;q();while(b=t(this.selector)){a.push(b),t(this.comment);if(!t(","))break;t(this.comment)}if(a.length>0&&(c=t(this.block)))return new e.Ruleset(a,c);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))&&t(";"))return new e.Import(a,p)},directive:function(){var a,c,d,g;if(b.charAt(f)!=="@")return;if(c=t(this["import"]))return c;if(a=t(/^@media|@page/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)||t("keyframes")){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!u(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getLocation(index) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: index ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var lines = input.split('\n'), + loc = getLocation(e.index), + line = loc.line, + col = loc.column; + + this.type = e.type || 'SyntaxError'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call) + 1); + this.callExtract = lines[getLocation(e.call)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if (parser.imports.error) { throw parser.imports.error } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features) { + var that = this; + + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
      ', + '
    • {0}
    • ', + '
    • {current}
    • ', + '
    • {2}
    • ', + '
    '].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    ' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js new file mode 100644 index 0000000..84e9047 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cm&&(l[h]=l[h].slice(g-m),m=g)}function v(a){var c,d,e,f,i,j,k,o;if(a instanceof Function)return a.call(n.parsers);if(typeof a=="string")c=b.charAt(g)===a?a:null,e=1,u();else{u();if(c=a.exec(l[h]))e=c[0].length;else return null}if(c){o=g+=e,j=g+l[h].length-e;while(g=0&&b.charAt(c)!=="\n";c--)d++;return{line:a?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,c){var d=b.split("\n"),e=z(a.index),f=e.line,g=e.column;this.type=a.type||"SyntaxError",this.message=a.message,this.filename=a.filename||c.filename,this.index=a.index,this.line=typeof f=="number"?f+1:null,this.callLine=a.call&&z(a.call)+1,this.callExtract=d[z(a.call)],this.stack=a.stack,this.column=g,this.extract=[d[f-1],d[f],d[f+1]]}var b,g,h,i,j,k,l,m,n,o=this,q=function(){},r=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&q()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,n={imports:r,parse:function(e,i){var j,o,p,r,s,t,u=[],w,x=null;g=h=m=k=0,l=[],b=e.replace(/\r\n/g,"\n"),l=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],v(this.parsers.primary)),j.root=!0}catch(y){return i(new A(y,a))}j.toCSS=function(b){var e,g,h;return function(e,g){var h=[];e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var i=b.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(j){throw new A(j,a)}if(n.imports.error)throw n.imports.error;return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(i):e.compress?i.replace(/(\s)+/g,"$1"):i}}(j.eval);if(g=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:g,filename:a.filename,line:s,column:B,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?q=function(){i(x,j)}:i(x,j)},parsers:{primary:function(){var a,b=[];while((a=v(this.mixin.definition)||v(this.rule)||v(this.ruleset)||v(this.mixin.call)||v(this.comment)||v(this.directive))||v(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(g)!=="/")return;if(b.charAt(g+1)==="/")return new f.Comment(v(/^\/\/.*/),!0);if(a=v(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&v("~");if(a=v(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=v(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,b,c=g;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(l[h])))return;a=a[1].toLowerCase();if(a==="url")return null;g+=a.length;if(a==="alpha")return v(this.alpha);v("("),b=v(this.entities.arguments);if(!v(")"))return;if(a)return new f.Call(a,b,c)},arguments:function(){var a=[],b;while(b=v(this.entities.assignment)||v(this.expression)){a.push(b);if(!v(","))break}return a},literal:function(){return v(this.entities.dimension)||v(this.entities.color)||v(this.entities.quoted)},assignment:function(){var a,b;if((a=v(/^\w+(?=\s?=)/i))&&v("=")&&(b=v(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(b.charAt(g)!=="u"||!v(/^url\(/))return;return a=v(this.entities.quoted)||v(this.entities.variable)||v(this.entities.dataURI)||v(/^[-\w%@$\/.&=:;#+?~]+/)||"",w(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),r.paths)},dataURI:function(){var a;if(v(/^data:/)){a={},a.mime=v(/^[^\/]+\/[^,;)]+/)||"",a.charset=v(/^;\s*charset=[^,;)]+/)||"",a.base64=v(/^;\s*base64/)||"",a.data=v(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=g;if(b.charAt(g)==="@"&&(a=v(/^@@?[\w-]+/)))return new f.Variable(a,c)},color:function(){var a;if(b.charAt(g)==="#"&&(a=v(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(g);if(c>57||c<45||c===47)return;if(a=v(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&v("~");if(a=v(/^`([^`]*)`/))return new f.JavaScript(a[1],g,d)}},variable:function(){var a;if(b.charAt(g)==="@"&&(a=v(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!y(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=v(this.entity))&&v("/")&&(b=v(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,h=g,i=b.charAt(g),j=!1;if(i!=="."&&i!=="#")return;while(c=v(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,g)),d=v(">");v("(")&&(e=v(this.entities.arguments))&&v(")"),v(this.important)&&(j=!0);if(a.length>0&&(v(";")||y("}")))return new f.mixin.Call(a,e,h,j)},definition:function(){var a,c=[],d,e,h,i,j;if(b.charAt(g)!=="."&&b.charAt(g)!=="#"||y(/^[^{]*(;|})/))return;s();if(d=v(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=v(this.entities.variable)||v(this.entities.literal)||v(this.entities.keyword)){h instanceof f.Variable?v(":")?(i=w(this.expression,"expected expression"),c.push({name:h.name,value:i})):c.push({name:h.name}):c.push({value:h});if(!v(","))break}w(")"),v(/^when/)&&(j=w(this.conditions,"expected condition")),e=v(this.block);if(e)return new f.mixin.Definition(a,c,e,j);t()}}},entity:function(){return v(this.entities.literal)||v(this.entities.variable)||v(this.entities.url)||v(this.entities.call)||v(this.entities.keyword)||v(this.entities.javascript)||v(this.comment)},end:function(){return v(";")||y("}")},alpha:function(){var a;if(!v(/^\(opacity=/i))return;if(a=v(/^\d+/)||v(this.entities.variable))return w(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=v(this.combinator),a=v(/^(?:\d+\.\d+|\d+)%/)||v(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||v("*")||v(this.attribute)||v(/^\([^)@]+\)/),a||v("(")&&(d=v(this.entities.variable))&&v(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,g);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,g)},combinator:function(){var a,c=b.charAt(g);if(c===">"||c==="+"||c==="~"){g++;while(b.charAt(g)===" ")g++;return new f.Combinator(c)}if(c==="&"){a="&",g++,b.charAt(g)===" "&&(a="& ");while(b.charAt(g)===" ")g++;return new f.Combinator(a)}if(c===":"&&b.charAt(g+1)===":"){g+=2;while(b.charAt(g)===" ")g++;return new f.Combinator("::")}return b.charAt(g-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,c,d=[],e,h;while(c=v(this.element)){e=b.charAt(g),d.push(c);if(e==="{"||e==="}"||e===";"||e===",")break}if(d.length>0)return new f.Selector(d)},tag:function(){return v(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||v("*")},attribute:function(){var a="",b,c,d;if(!v("["))return;if(b=v(/^[a-zA-Z-]+/)||v(this.entities.quoted))(d=v(/^[|~*$^]?=/))&&(c=v(this.entities.quoted)||v(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!v("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(v("{")&&(a=v(this.primary))&&v("}"))return a},ruleset:function(){var a=[],b,c,d;s();while(b=v(this.selector)){a.push(b),v(this.comment);if(!v(","))break;v(this.comment)}if(a.length>0&&(c=v(this.block)))return new f.Ruleset(a,c);k=g,t()},rule:function(){var a,c,d=b.charAt(g),e,i;s();if(d==="."||d==="#"||d==="&")return;if(a=v(this.variable)||v(this.property)){a.charAt(0)!="@"&&(i=/^([^@+\/'"*`(;{}-]*);/.exec(l[h]))?(g+=i[0].length-1,c=new f.Anonymous(i[1])):a==="font"?c=v(this.font):c=v(this.value),e=v(this.important);if(c&&v(this.end))return new f.Rule(a,c,e,j);k=g,t()}},"import":function(){var a,b;if(v(/^@import\s+/)&&(a=v(this.entities.quoted)||v(this.entities.url))){b=v(this.mediaFeatures);if(v(";"))return new f.Import(a,r,b)}},mediaFeature:function(){var a=[];do if(e=v(this.entities.keyword))a.push(e);else if(v("(")){p=v(this.property),e=v(this.entity);if(!v(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,g,!0)));else if(e)a.push(new f.Paren(e));else return null}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=v(this.mediaFeature)){b.push(a);if(!v(","))break}return b.length>0?b:null},media:function(){var a;if(v(/^@media/)){a=v(this.mediaFeatures);if(rules=v(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,c,d,e,h,i;if(b.charAt(g)!=="@")return;if(c=v(this["import"])||v(this.media))return c;if(a=v(/^@page|@keyframes/)||v(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){e=(v(/^[^{]+/)||"").trim();if(d=v(this.block))return new f.Directive(a+" "+e,d)}else if(a=v(/^@[-a-z]+/))if(a==="@font-face"){if(d=v(this.block))return new f.Directive(a,d)}else if((c=v(this.entity))&&v(";"))return new f.Directive(a,c)},font:function(){var a=[],b=[],c,d,e,g;while(g=v(this.shorthand)||v(this.entity))b.push(g);a.push(new f.Expression(b));if(v(","))while(g=v(this.expression)){a.push(g);if(!v(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=v(this.expression)){b.push(a);if(!v(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(b.charAt(g)==="!")return v(/^! *important/)},sub:function(){var a;if(v("(")&&(a=v(this.expression))&&v(")"))return a},multiplication:function(){var a,b,c,d;if(a=v(this.operand)){while(!y(/^\/\*/)&&(c=v("/")||v("*"))&&(b=v(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,e;if(a=v(this.multiplication)){while((d=v(/^[-+]\s+/)||b.charAt(g-1)!=" "&&(v("+")||v("-")))&&(c=v(this.multiplication)))e=new f.Operation(d,[e||a,c]);return e||a}},conditions:function(){var a,b,c=g,d;if(a=v(this.condition)){while(v(",")&&(b=v(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=g,h=!1;v(/^not/)&&(h=!0),w("(");if(a=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))return(d=v(/^(?:>=|=<|[<=>])/))?(b=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))?c=new f.Condition(d,a,b,e,h):x("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,h),w(")"),v(/^and/)?new f.Condition("and",c,v(this.condition)):c},operand:function(){var a,c=b.charAt(g+1);b.charAt(g)==="-"&&(c==="@"||c==="(")&&(a=v("-"));var d=v(this.sub)||v(this.entities.dimension)||v(this.entities.color)||v(this.entities.variable)||v(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=v(this.addition)||v(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=v(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d){var e=this;this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a,b){e.root=b})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&r(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input) + 1); + this.callExtract = lines[getLocation(e.call, input)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js new file mode 100644 index 0000000..89b7637 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&B(a.call,c)+1,this.callExtract=g[B(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return a.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function basename(pathname) { + if (less.mode === 'node') { + return require('path').basename(pathname); + } else { + return pathname.match(/[^\/]+$/)[0]; + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[basename(e.filename)]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input) + 1); + this.callExtract = lines[getLocation(e.call, input)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)\\]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join( env.compress ? ',' : ',\n'); + + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js new file mode 100644 index 0000000..55042ec --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function D(a,b){var c=B(a,b),d=C(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&C(a.call,c)+1,this.callExtract=g[C(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)\\]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=a[0],k;for(var l=0,m,n;l0&&(x=new D({index:l,type:"Parse",message:"missing closing `}`",filename:b.filename},b)),a.map(function(a){return a.join("")})}([[]]);if(x)return e(x);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new D(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new D(k,b)}if(i=o.imports.error)throw i instanceof D?i:new D(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function basename(pathname) { + if (less.mode === 'node') { + return require('path').basename(pathname); + } else { + return pathname.match(/[^\/]+$/)[0]; + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[basename(e.filename)]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)\\]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args || [], index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules, env.strictImports); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Media)(rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var el = new(tree.Element)('&', null, 0), + selectors = [new(tree.Selector)([el])]; + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var el = new(tree.Element)('&', null, 0); + var selectors = [new(tree.Selector)([el])]; + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs; + + for (var i = 0, val, name; i < this.params.length; i++) { + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join( env.compress ? ',' : ',\n'); + + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js new file mode 100644 index 0000000..309bf55 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,b){var c=y(a,b),d=z(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&z(a.call,c).line+1,this.callExtract=g[z(a.call,c).line],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var b,f,g,h,i,j,k,l,m,n=this,o=function(){},p=this.imports={paths:a&&a.paths||[],queue:[],files:{},contents:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d,f){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,e.contents[b]=f,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&o()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,m={imports:p,parse:function(h,i){var n,p,q,r,s,u,v=[],w,x=null;f=g=l=j=0,b=h.replace(/\r\n/g,"\n"),k=function(c){var d=0,e=/[^"'`\{\}\/\(\)\\]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=c[0],k;for(var l=0,m,n;l0&&(x=new A({index:l,type:"Parse",message:"missing closing `}`",filename:a.filename},a)),c.map(function(a){return a.join("")})}([[]]);if(x)return i(x);try{n=new e.Ruleset([],t(this.parsers.primary)),n.root=!0}catch(y){return i(new A(y,a))}n.toCSS=function(b){var f,g,h;return function(f,g){var h=[],i;f=f||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),h=[new e.Ruleset(null,g)]);try{var j=b.call(this,{frames:h}).toCSS([],{compress:f.compress||!1})}catch(k){throw new A(k,a)}if(i=m.imports.error)throw i instanceof A?i:new A(i,a);return f.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):f.compress?j.replace(/(\s)+/g,"$1"):j}}(n.eval);if(f=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:f,filename:a.filename,line:s,column:B,extract:[u[s-2],u[s-1],u[s]]}}this.imports.queue.length>0?o=function(){i(x,n)}:i(x,n)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var b,c,d=f;if(!(b=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;b=b[1].toLowerCase();if(b==="url")return null;f+=b.length;if(b==="alpha")return t(this.alpha);t("("),c=t(this.entities.arguments);if(!t(")"))return;if(b)return new e.Call(b,c,d,a.filename)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;return a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"",u(")"),new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var c,d=f;if(b.charAt(f)==="@"&&(c=t(/^@@?[\w-]+/)))return new e.Variable(c,d,a.filename)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!w(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var c=[],d,g,h,i=f,j=b.charAt(f),k=!1;if(j!=="."&&j!=="#")return;while(d=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))c.push(new e.Element(g,d,f)),g=t(">");t("(")&&(h=t(this.entities.arguments))&&t(")"),t(this.important)&&(k=!0);if(c.length>0&&(t(";")||w("}")))return new e.mixin.Call(c,h||[],i,a.filename,k)},definition:function(){var a,c=[],d,g,h,i,j,k=!1;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||w(/^[^{]*(;|})/))return;q();if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];do{if(b.charAt(f)==="."&&t(/^\.{3}/)){k=!0;break}if(!(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)))break;if(h instanceof e.Variable)if(t(":"))i=u(this.expression,"expected expression"),c.push({name:h.name,value:i});else{if(t(/^\.{3}/)){c.push({name:h.name,variadic:!0}),k=!0;break}c.push({name:h.name})}else c.push({value:h})}while(t(","));u(")"),t(/^when/)&&(j=u(this.conditions,"expected condition")),g=t(this.block);if(g)return new e.mixin.Definition(a,c,g,j,k);r()}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||w("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable))return u(")"),new e.Alpha(a)},element:function(){var a,b,c,d;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/),a||t("(")&&(d=t(this.entities.variable))&&t(")")&&(a=new e.Paren(d));if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;if(t("("))return a=t(this.entity),u(")"),new e.Selector([new e.Element("",a,f)]);while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var b=[],c,d,g;q();while(c=t(this.selector)){b.push(c),t(this.comment);if(!t(","))break;t(this.comment)}if(b.length>0&&(d=t(this.block)))return new e.Ruleset(b,d,a.strictImports);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a,b,c=f;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))){b=t(this.mediaFeatures);if(t(";"))return new e.Import(a,p,b,c)}},mediaFeature:function(){var a,b,c=[];do if(a=t(this.entities.keyword))c.push(a);else if(t("(")){b=t(this.property),a=t(this.entity);if(!t(")"))return null;if(b&&a)c.push(new e.Paren(new e.Rule(b,a,null,f,!0)));else if(a)c.push(new e.Paren(a));else return null}while(a);if(c.length>0)return new e.Expression(c)},mediaFeatures:function(){var a,b=[];do if(a=t(this.mediaFeature)){b.push(a);if(!t(","))break}else if(a=t(this.entities.variable)){b.push(a);if(!t(","))break}while(a);return b.length>0?b:null},media:function(){var a,b;if(t(/^@media/)){a=t(this.mediaFeatures);if(b=t(this.block))return new e.Media(b,a)}},directive:function(){var a,c,d,g,h,i;if(b.charAt(f)!=="@")return;if(c=t(this["import"])||t(this.media))return c;if(a=t(/^@page|@keyframes/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!w(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},conditions:function(){var a,b,c=f,d;if(a=t(this.condition)){while(t(",")&&(b=t(this.condition)))d=new e.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,g=f,h=!1;t(/^not/)&&(h=!0),u("(");if(a=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))return(d=t(/^(?:>=|=<|[<=>])/))?(b=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))?c=new e.Condition(d,a,b,g,h):v("expected expression"):c=new e.Condition("=",a,new e.Keyword("true"),g,h),u(")"),t(/^and/)?new e.Condition("and",c,t(this.condition)):c},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e1){var d=new a.Element("&",null,0),e=[new a.Selector([d])];c=new a.Ruleset(e,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(a.length===0)return[];if(a.length===1)return a[0];var b=[],c=this.permute(a.slice(1));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;gthis.params.length)return!1;if(this.required>0&&c>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c,d,e){b&&p(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = path in that.files; + + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + } + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { + e = new(tree.Paren)(v); + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ + loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) + * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); + } else if (typeof(n) === 'number') { + return n.toFixed(fraction); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs, arg; + + for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] + + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; + } + + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (arg && arg.value) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push((args[i] && args[i].value) || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules = []; + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + rules = []; + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + this.value = val; + this.paths = paths; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx); + + // Add the base path if the URL is relative and we are either + // a.) in the browser or + // b.) we have a relative file URL + if ((this.paths.length > 0) && + (typeof window !== 'undefined' || !/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0])) && + (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value))) { + var path = this.paths[0].slice(-1) === '/' ? this.paths[0] : this.paths[0] + '/'; + var v = path + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + val = new(tree.Anonymous)(v); + } + + return new(tree.URL)(val, this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); + if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)({ + filename: document.location.href.replace(/#.*$/, ''), + dumpLineNumbers: less.dumpLineNumbers + }).parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var contents = sheet.contents || {}; // Passing a ref to top importing parser content cache trough 'sheet' arg. + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^[a-z-]+:/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + contents[href] = data; // Updating top importing parser content cache + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: href, + 'contents': contents, // Passing top importing parser content cache ref down. + dumpLineNumbers: less.dumpLineNumbers + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + if( sheet.media ){ css.media = sheet.media; } + css.id = id; + var nextEl = sheet && sheet.nextSibling || null; + document.getElementsByTagName('head')[0].insertBefore(css, nextEl); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + var filenameNoPath = filename.match(/([^\/]+)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define("less", [], function () { return less; } ); +} +})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js new file mode 100644 index 0000000..42b67f0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(e,t){function n(t){return e.less[t.split("/")[1]]}function h(){var e=document.getElementsByTagName("style");for(var t=0;t0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&u){w("saving "+i+" to cache.");try{u.setItem(i,e),u.setItem(i+":timestamp",n)}catch(a){w("failed to save")}}}function g(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var o=y(),u=s?r.fileAsync:r.async;typeof o.overrideMimeType=="function"&&o.overrideMimeType("text/css"),o.open("GET",e,u),o.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),o.send(null),s&&!r.fileAsync?o.status===0||o.status>=200&&o.status<300?n(o.responseText):i(o.status,e):u?o.onreadystatechange=function(){o.readyState==4&&a(o,n,i)}:a(o,n,i)}function y(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return w("browser doesn't support AJAX."),null}}function b(e){return e&&e.parentNode.removeChild(e)}function w(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function E(e,t){var n="less-error-message:"+v(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,m([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={});var v=function(){},m=this.imports={paths:t&&t.paths||[],queue:[],files:{},contents:t.contents,mime:t&&t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r){i.queue.splice(i.queue.indexOf(e),1);var s=e in i.files;i.files[e]=r,t&&!i.error&&(i.error=t),n(t,r,s),i.queue.length===0&&v(t)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0&&(x=new O({index:c,type:"Parse",message:"missing closing `}`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("./cssmin").compressor.cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),m.paths)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<45||t===47)return;if(e=E(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a,f=o,l=s.charAt(o),c,h,p=!1;if(l!=="."&&l!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){while(a=E(this.expression)){h=a,c=null;if(a.value.length==1){var d=a.value[0];if(d instanceof i.Variable&&E(":")){if(!(h=E(this.expression)))throw new Error("Expected value");c=d.name}}u.push({name:c,value:h});if(!E(","))break}if(!E(")"))throw new Error("Expected )")}E(this.important)&&(p=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,u,f,t.filename,p);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*(;|})/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0;break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(","));E(")")||(l=o,y()),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^)@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),x(")"),new i.Selector([new i.Element("",e,o)]);while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===",")break}if(n.length>0)return new i.Selector(n)},tag:function(){return E(/^[A-Za-z][A-Za-z-]*[0-9]?/)||E("*")},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,t,n=o;g();var r=E(/^@import(?:-(once))?\s+/);if(r&&(e=E(this.entities.quoted)||E(this.entities.url))){t=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,t,r[1]==="once",n)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,t,n,r,u,a,f,l,c;if(s.charAt(o)!=="@")return;if(t=E(this["import"])||E(this.media))return t;g(),e=E(/^@[a-z-]+/),f=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(f="@"+e.slice(e.indexOf("-",2)+1));switch(f){case"@font-face":l=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":l=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":l=!0,c=!0}c&&(e+=" "+(E(/^[^{]+/)||"").trim());if(l){if(n=E(this.block))return new i.Directive(e,n)}else if((t=E(this.entity))&&E(";"))return new i.Directive(e,t);y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/\*/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),d({href:e,title:e,type:r.mime,contents:r.contents},function(i){i&&typeof r.errback=="function"?r.errback.call(null,e,t,n,r):n.apply(null,arguments)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function r(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,r,i,s){var o=[t,r,i].map(function(e){return n(e)}),s=n(s);return new e.Color(o,s)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,r,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=n(e)%360/360,t=n(t),r=n(r),i=n(i);var s=r<=.5?r*(t+1):r+t-r*t,o=r*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var i=e.toHSL();return i.s+=n.value/100,i.s=r(i.s),t(i)},desaturate:function(e,n){var i=e.toHSL();return i.s-=n.value/100,i.s=r(i.s),t(i)},lighten:function(e,n){var i=e.toHSL();return i.l+=n.value/100,i.l=r(i.l),t(i)},darken:function(e,n){var i=e.toHSL();return i.l-=n.value/100,i.l=r(i.l),t(i)},fadein:function(e,n){var i=e.toHSL();return i.a+=n.value/100,i.a=r(i.a),t(i)},fadeout:function(e,n){var i=e.toHSL();return i.a-=n.value/100,i.a=r(i.a),t(i)},fade:function(e,n){var i=e.toHSL();return i.a=n.value/100,i.a=r(i.a),t(i)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t, +n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s){var o=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),t instanceof e.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css(\?.*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&o.once&&(o.skip=r),o.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?"@import "+this._path.toCSS()+t+";\n":""},eval:function(t){var n,r=this.features&&this.features.eval(t);if(this.skip)return[];if(this.css)return this;n=new e.Ruleset([],this.root.rules.slice(0));for(var i=0;i1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){n=this.arguments&&this.arguments.map(function(t){return{name:t.name,value:t.value.eval(e)}});for(var o=0;othis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(t,e)].concat(t.frames)}))return!1;r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements.length,n=e.elements.length,r=Math.min(t,n);if(t0&&(typeof e!="undefined"||!/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0]))&&typeof r.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(r.value)){var i=this.paths[0].slice(-1)==="/"?this.paths[0]:this.paths[0]+"/",s=i+(r.value.charAt(0)==="/"?r.value.slice(1):r.value);r=new t.Anonymous(s)}return new t.URL(r,this.paths)}}}(n("../tree")),function(e){e.Value=function(e){this.value=e,this.is="value"},e.Value.prototype={eval:function(t){return this.value.length===1?this.value[0].eval(t):new e.Value(this.value.map(function(e){return e.eval(t)}))},toCSS:function(e){return this.value.map(function(t){return t.toCSS(e)}).join(e.compress?",":", ")}}}(n("../tree")),function(e){e.Variable=function(e,t,n){this.name=e,this.index=t,this.file=n},e.Variable.prototype={eval:function(t){var n,r,i=this.name;i.indexOf("@@")==0&&(i="@"+(new e.Variable(i.slice(1))).eval(t).value);if(n=e.find(t.frames,function(e){if(r=e.variable(i))return r.value.eval(t)}))return n;throw{type:"Name",message:"variable "+i+" is undefined",filename:this.file,index:this.index}}}}(n("../tree")),function(e){e.debugInfo=function(t,n){var r="";if(t.dumpLineNumbers&&!t.compress)switch(t.dumpLineNumbers){case"comments":r=e.debugInfo.asComment(n);break;case"mediaquery":r=e.debugInfo.asMediaQuery(n);break;case"all":r=e.debugInfo.asComment(n)+e.debugInfo.asMediaQuery(n)}return r},e.debugInfo.asComment=function(e){return"/* line "+e.debugInfo.lineNumber+", "+e.debugInfo.fileName+" */\n"},e.debugInfo.asMediaQuery=function(e){return'@media -sass-debug-info{filename{font-family:"'+e.debugInfo.fileName+'";}line{font-family:"'+e.debugInfo.lineNumber+'";}}\n'},e.find=function(e,t){for(var n=0,r;n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var s=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||s?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(s?1e3:1500),r.watch=function(){return this.watchMode=!0},r.unwatch=function(){return this.watchMode=!1};if(r.env==="development"){r.optimization=0,/!watch/.test(location.hash)&&r.watch();var o=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);o&&(r.dumpLineNumbers=o[1]),r.watchTimer=setInterval(function(){r.watchMode&&p(function(e,t,n,r,i){t&&m(t.toCSS(),r,i.lastModified)})},r.poll)}else r.optimization=3;var u;try{u=typeof e.localStorage=="undefined"?null:e.localStorage}catch(a){u=null}var f=document.getElementsByTagName("link"),l=/^text\/(x-)?less$/;r.sheets=[];for(var c=0;c>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + if (typeof(exports) === 'undefined') { + // Rhino + less = {}; + tree = less.tree = {}; + } else { + // Node.js + less = exports, + tree = require('less/tree'); + } +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + + if (c.value && c.value[0] === '&') { + return new(tree.Element)(c, null); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined' /* browser */ || typeof(exports) === 'undefined' /* rhino */) { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function( paths, context, selectors ) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function( paths, context, selector ) { + var before = [], after = [], beforeElements = [], afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value[0] === '&') { + hasParentSelector = true; + } + if(!hasParentSelector) { + beforeElements.push(el); + } else { + afterElements.push(el); + } + } + + if(!hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if(beforeElements.length > 0) { + before.push(new (tree.Selector)(beforeElements)); + } + if(afterElements.length > 0) { + after.push(new (tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; + var input = readFile(sheetName); + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + print("Error: " + e); + quit(1); + } + callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); + }); + + // callback({}, sheet, { local: true, remaining: remaining }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + name = args[0]; + var output = args[1]; + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + quit(1); + } else { + result = root.toCSS(); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + print("done"); +}(arguments)); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js b/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js new file mode 100644 index 0000000..e755f63 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js @@ -0,0 +1,2481 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'rhino'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/\/|file:\/\/|data:)?/.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; + var input = readFile(sheetName); + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + print("Error: " + e); + quit(1); + } + callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); + }); + + // callback({}, sheet, { local: true, remaining: remaining }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + name = args[0]; + var output = args[1]; + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + quit(1); + } else { + result = root.toCSS(); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + print("done"); +}(arguments)); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/browser.js b/enyo/tools/minifier/node_modules/less/lib/less/browser.js new file mode 100644 index 0000000..a9f577f --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/browser.js @@ -0,0 +1,394 @@ +// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); + if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)({ + filename: document.location.href.replace(/#.*$/, ''), + dumpLineNumbers: less.dumpLineNumbers + }).parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var contents = sheet.contents || {}; // Passing a ref to top importing parser content cache trough 'sheet' arg. + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^[a-z-]+:/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + contents[href] = data; // Updating top importing parser content cache + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: href, + 'contents': contents, // Passing top importing parser content cache ref down. + dumpLineNumbers: less.dumpLineNumbers + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + if( sheet.media ){ css.media = sheet.media; } + css.id = id; + var nextEl = sheet && sheet.nextSibling || null; + document.getElementsByTagName('head')[0].insertBefore(css, nextEl); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + var filenameNoPath = filename.match(/([^\/]+)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + diff --git a/enyo/tools/minifier/node_modules/less/lib/less/colors.js b/enyo/tools/minifier/node_modules/less/lib/less/colors.js new file mode 100644 index 0000000..b417af6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/colors.js @@ -0,0 +1,152 @@ +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js b/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js new file mode 100644 index 0000000..427de71 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js @@ -0,0 +1,355 @@ +/** + * cssmin.js + * Author: Stoyan Stefanov - http://phpied.com/ + * This is a JavaScript port of the CSS minification tool + * distributed with YUICompressor, itself a port + * of the cssmin utility by Isaac Schlueter - http://foohack.com/ + * Permission is hereby granted to use the JavaScript version under the same + * conditions as the YUICompressor (original YUICompressor note below). + */ + +/* +* YUI Compressor +* http://developer.yahoo.com/yui/compressor/ +* Author: Julien Lecomte - http://www.julienlecomte.net/ +* Copyright (c) 2011 Yahoo! Inc. All rights reserved. +* The copyrights embodied in the content of this file are licensed +* by Yahoo! Inc. under the BSD (revised) open source license. +*/ +var YAHOO = YAHOO || {}; +YAHOO.compressor = YAHOO.compressor || {}; + +/** + * Utility method to replace all data urls with tokens before we start + * compressing, to avoid performance issues running some of the subsequent + * regexes against large strings chunks. + * + * @private + * @method _extractDataUrls + * @param {String} css The input css + * @param {Array} The global array of tokens to preserve + * @returns String The processed css + */ +YAHOO.compressor._extractDataUrls = function (css, preservedTokens) { + + // Leave data urls alone to increase parse performance. + var maxIndex = css.length - 1, + appendIndex = 0, + startIndex, + endIndex, + terminator, + foundTerminator, + sb = [], + m, + preserver, + token, + pattern = /url\(\s*(["']?)data\:/g; + + // Since we need to account for non-base64 data urls, we need to handle + // ' and ) being part of the data string. Hence switching to indexOf, + // to determine whether or not we have matching string terminators and + // handling sb appends directly, instead of using matcher.append* methods. + + while ((m = pattern.exec(css)) !== null) { + + startIndex = m.index + 4; // "url(".length() + terminator = m[1]; // ', " or empty (not quoted) + + if (terminator.length === 0) { + terminator = ")"; + } + + foundTerminator = false; + + endIndex = pattern.lastIndex - 1; + + while(foundTerminator === false && endIndex+1 <= maxIndex) { + endIndex = css.indexOf(terminator, endIndex + 1); + + // endIndex == 0 doesn't really apply here + if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) { + foundTerminator = true; + if (")" != terminator) { + endIndex = css.indexOf(")", endIndex); + } + } + } + + // Enough searching, start moving stuff over to the buffer + sb.push(css.substring(appendIndex, m.index)); + + if (foundTerminator) { + token = css.substring(startIndex, endIndex); + token = token.replace(/\s+/g, ""); + preservedTokens.push(token); + + preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)"; + sb.push(preserver); + + appendIndex = endIndex + 1; + } else { + // No end terminator found, re-add the whole match. Should we throw/warn here? + sb.push(css.substring(m.index, pattern.lastIndex)); + appendIndex = pattern.lastIndex; + } + } + + sb.push(css.substring(appendIndex)); + + return sb.join(""); +}; + +/** + * Utility method to compress hex color values of the form #AABBCC to #ABC. + * + * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). + * e.g. #AddressForm { ... } + * + * DOES NOT compress IE filters, which have hex color values (which would break things). + * e.g. filter: chroma(color="#FFFFFF"); + * + * DOES NOT compress invalid hex values. + * e.g. background-color: #aabbccdd + * + * @private + * @method _compressHexColors + * @param {String} css The input css + * @returns String The processed css + */ +YAHOO.compressor._compressHexColors = function(css) { + + // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) + var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi, + m, + index = 0, + isFilter, + sb = []; + + while ((m = pattern.exec(css)) !== null) { + + sb.push(css.substring(index, m.index)); + + isFilter = m[1]; + + if (isFilter) { + // Restore, maintain case, otherwise filter will break + sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7])); + } else { + if (m[2].toLowerCase() == m[3].toLowerCase() && + m[4].toLowerCase() == m[5].toLowerCase() && + m[6].toLowerCase() == m[7].toLowerCase()) { + + // Compress. + sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase()); + } else { + // Non compressible color, restore but lower case. + sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase()); + } + } + + index = pattern.lastIndex = pattern.lastIndex - m[8].length; + } + + sb.push(css.substring(index)); + + return sb.join(""); +}; + +YAHOO.compressor.cssmin = function (css, linebreakpos) { + + var startIndex = 0, + endIndex = 0, + i = 0, max = 0, + preservedTokens = [], + comments = [], + token = '', + totallen = css.length, + placeholder = ''; + + css = this._extractDataUrls(css, preservedTokens); + + // collect all comment blocks... + while ((startIndex = css.indexOf("/*", startIndex)) >= 0) { + endIndex = css.indexOf("*/", startIndex + 2); + if (endIndex < 0) { + endIndex = totallen; + } + token = css.slice(startIndex + 2, endIndex); + comments.push(token); + css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex); + startIndex += 2; + } + + // preserve strings so their content doesn't get accidentally minified + css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) { + var i, max, quote = match.substring(0, 1); + + match = match.slice(1, -1); + + // maybe the string contains a comment-like substring? + // one, maybe more? put'em back then + if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { + for (i = 0, max = comments.length; i < max; i = i + 1) { + match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]); + } + } + + // minify alpha opacity in filter strings + match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); + + preservedTokens.push(match); + return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote; + }); + + // strings are safe, now wrestle the comments + for (i = 0, max = comments.length; i < max; i = i + 1) { + + token = comments[i]; + placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; + + // ! in the first position of the comment means preserve + // so push to the preserved tokens keeping the ! + if (token.charAt(0) === "!") { + preservedTokens.push(token); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + continue; + } + + // \ in the last position looks like hack for Mac/IE5 + // shorten that to /*\*/ and the next one to /**/ + if (token.charAt(token.length - 1) === "\\") { + preservedTokens.push("\\"); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + i = i + 1; // attn: advancing the loop + preservedTokens.push(""); + css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + continue; + } + + // keep empty comments after child selectors (IE7 hack) + // e.g. html >/**/ body + if (token.length === 0) { + startIndex = css.indexOf(placeholder); + if (startIndex > 2) { + if (css.charAt(startIndex - 3) === '>') { + preservedTokens.push(""); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + } + } + } + + // in all other cases kill the comment + css = css.replace("/*" + placeholder + "*/", ""); + } + + + // Normalize all whitespace strings to single spaces. Easier to work with that way. + css = css.replace(/\s+/g, " "); + + // Remove the spaces before the things that should not have spaces before them. + // But, be careful not to turn "p :link {...}" into "p:link{...}" + // Swap out any pseudo-class colons with the token, and then swap back. + css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) { + return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___"); + }); + css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1'); + css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":"); + + // retain space for special IE6 cases + css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2"); + + // no space after the end of a preserved comment + css = css.replace(/\*\/ /g, '*/'); + + + // If there is a @charset, then only allow one, and push to the top of the file. + css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1'); + css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1'); + + // Put the space back in some cases, to support stuff like + // @media screen and (-webkit-min-device-pixel-ratio:0){ + css = css.replace(/\band\(/gi, "and ("); + + + // Remove the spaces after the things that should not have spaces after them. + css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1'); + + // remove unnecessary semicolons + css = css.replace(/;+\}/g, "}"); + + // Replace 0(px,em,%) with 0. + css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2"); + + // Replace 0 0 0 0; with 0. + css = css.replace(/:0 0 0 0(;|\})/g, ":0$1"); + css = css.replace(/:0 0 0(;|\})/g, ":0$1"); + css = css.replace(/:0 0(;|\})/g, ":0$1"); + + // Replace background-position:0; with background-position:0 0; + // same for transform-origin + css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) { + return prop.toLowerCase() + ":0 0" + tail; + }); + + // Replace 0.6 to .6, but only when preceded by : or a white-space + css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2"); + + // Shorten colors from rgb(51,102,153) to #336699 + // This makes it more likely that it'll get further compressed in the next step. + css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () { + var i, rgbcolors = arguments[1].split(','); + for (i = 0; i < rgbcolors.length; i = i + 1) { + rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16); + if (rgbcolors[i].length === 1) { + rgbcolors[i] = '0' + rgbcolors[i]; + } + } + return '#' + rgbcolors.join(''); + }); + + // Shorten colors from #AABBCC to #ABC. + css = this._compressHexColors(css); + + // border: none -> border:0 + css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) { + return prop.toLowerCase() + ":0" + tail; + }); + + // shorter opacity IE filter + css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); + + // Remove empty rules. + css = css.replace(/[^\};\{\/]+\{\}/g, ""); + + if (linebreakpos >= 0) { + // Some source control tools don't like it when files containing lines longer + // than, say 8000 characters, are checked in. The linebreak option is used in + // that case to split long lines after a specific column. + startIndex = 0; + i = 0; + while (i < css.length) { + i = i + 1; + if (css[i - 1] === '}' && i - startIndex > linebreakpos) { + css = css.slice(0, i) + '\n' + css.slice(i); + startIndex = i; + } + } + } + + // Replace multiple semi-colons in a row by a single one + // See SF bug #1980989 + css = css.replace(/;;+/g, ";"); + + // restore preserved comments and strings + for (i = 0, max = preservedTokens.length; i < max; i = i + 1) { + css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]); + } + + // Trim the final string (for any leading or trailing white spaces) + css = css.replace(/^\s+|\s+$/g, ""); + + return css; + +}; + +exports.compressor = YAHOO.compressor; diff --git a/enyo/tools/minifier/node_modules/less/lib/less/functions.js b/enyo/tools/minifier/node_modules/less/lib/less/functions.js new file mode 100644 index 0000000..2e0cc51 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/functions.js @@ -0,0 +1,337 @@ +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) + * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); + } else if (typeof(n) === 'number') { + return n.toFixed(fraction); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/index.js b/enyo/tools/minifier/node_modules/less/lib/less/index.js new file mode 100644 index 0000000..7ffbbcf --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/index.js @@ -0,0 +1,140 @@ +var path = require('path'), + sys = require('util'), + fs = require('fs'); + +var less = { + version: [1, 3, 0], + Parser: require('./parser').Parser, + importer: require('./parser').importer, + tree: require('./tree'), + render: function (input, options, callback) { + options = options || {}; + + if (typeof(options) === 'function') { + callback = options, options = {}; + } + + var parser = new(less.Parser)(options), + ee; + + if (callback) { + parser.parse(input, function (e, root) { + callback(e, root && root.toCSS && root.toCSS(options)); + }); + } else { + ee = new(require('events').EventEmitter); + + process.nextTick(function () { + parser.parse(input, function (e, root) { + if (e) { ee.emit('error', e) } + else { ee.emit('success', root.toCSS(options)) } + }); + }); + return ee; + } + }, + formatError: function(ctx, options) { + options = options || {}; + + var message = ""; + var extract = ctx.extract; + var error = []; + var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str }; + + if (ctx.stack) { return stylize(ctx.stack, 'red') } + + if (!ctx.hasOwnProperty('index')) { + return ctx.stack || ctx.message; + } + + if (typeof(extract[0]) === 'string') { + error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); + } + + if (extract[1]) { + error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) + + stylize(stylize(stylize(extract[1][ctx.column], 'bold') + + extract[1].slice(ctx.column + 1), 'red'), 'inverse')); + } + + if (typeof(extract[2]) === 'string') { + error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); + } + error = error.join('\n') + stylize('', 'reset') + '\n'; + + message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); + ctx.filename && (message += stylize(' in ', 'red') + ctx.filename + + stylize(':' + ctx.line + ':' + ctx.column, 'grey')); + + message += '\n' + error; + + if (ctx.callLine) { + message += stylize('from ', 'red') + (ctx.filename || '') + '/n'; + message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n'; + } + + return message; + }, + writeError: function (ctx, options) { + options = options || {}; + if (options.silent) { return } + sys.error(less.formatError(ctx, options)); + } +}; + +['color', 'directive', 'operation', 'dimension', + 'keyword', 'variable', 'ruleset', 'element', + 'selector', 'quoted', 'expression', 'rule', + 'call', 'url', 'alpha', 'import', + 'mixin', 'comment', 'anonymous', 'value', + 'javascript', 'assignment', 'condition', 'paren', + 'media', 'ratio' +].forEach(function (n) { + require('./tree/' + n); +}); + +less.Parser.importer = function (file, paths, callback, env) { + var pathname; + + // TODO: Undo this at some point, + // or use different approach. + var paths = [].concat(paths); // Avoid passing paths by reference down the import tree... + paths.unshift('.'); // ...which results on a lot of repeated '.' paths. + + for (var i = 0; i < paths.length; i++) { + try { + pathname = path.join(paths[i], file); + fs.statSync(pathname); + break; + } catch (e) { + pathname = null; + } + } + + if (pathname) { + fs.readFile(pathname, 'utf-8', function(e, data) { + if (e) return callback(e); + + env.contents[pathname] = data; // Updating top importing parser content cache. + new(less.Parser)({ + paths: [path.dirname(pathname)].concat(paths), + filename: pathname, + contents: env.contents, + dumpLineNumbers: env.dumpLineNumbers + }).parse(data, function (e, root) { + callback(e, root); + }); + }); + } else { + if (typeof(env.errback) === "function") { + env.errback(file, paths, callback); + } else { + callback({ type: 'File', message: "'" + file + "' wasn't found.\n" }); + } + } +} + +require('./functions'); +require('./colors'); + +for (var k in less) { exports[k] = less[k] } diff --git a/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js b/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js new file mode 100644 index 0000000..7c051be --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js @@ -0,0 +1,59 @@ +// lessc_helper.js +// +// helper functions for lessc +sys = require('util'); + +var lessc_helper = { + + //Stylize a string + stylize : function(str, style) { + var styles = { + 'reset' : [0, 0], + 'bold' : [1, 22], + 'inverse' : [7, 27], + 'underline' : [4, 24], + 'yellow' : [33, 39], + 'green' : [32, 39], + 'red' : [31, 39], + 'grey' : [90, 39] + }; + return '\033[' + styles[style][0] + 'm' + str + + '\033[' + styles[style][1] + 'm'; + }, + + //Print command line options + printUsage: function() { + sys.puts("usage: lessc [options] [destination]"); + sys.puts(""); + sys.puts("If source is set to `-' (dash or hyphen-minus), input is read from stdin."); + sys.puts(""); + sys.puts("options:"); + sys.puts(" -h, --help Print help (this message) and exit."); + sys.puts(" --include-path Set include paths. Separated by `:'. Use `;' on Windows."); + sys.puts(" --no-color Disable colorized output."); + sys.puts(" -s, --silent Suppress output of error messages."); + sys.puts(" --strict-imports Force evaluation of imports."); + sys.puts(" --verbose Be verbose."); + sys.puts(" -v, --version Print version number and exit."); + sys.puts(" -x, --compress Compress output by removing some whitespaces."); + sys.puts(" --yui-compress Compress output using cssmin.js."); + sys.puts(" -O0, -O1, -O2 Set the parser's optimization level. The lower"); + sys.puts(" the number, the less nodes it will create in the"); + sys.puts(" tree. This could matter for debugging, or if you"); + sys.puts(" want to access the individual nodes in the tree."); + sys.puts(" --line-numbers=TYPE Outputs filename and line numbers."); + sys.puts(" TYPE can be either 'comments', which will output"); + sys.puts(" the debug info within comments, 'mediaquery'"); + sys.puts(" that will output the information within a fake"); + sys.puts(" media query which is compatible with the SASS"); + sys.puts(" format, and 'all' which will do both."); + sys.puts(""); + sys.puts("Report bugs to: http://github.com/cloudhead/less.js/issues"); + sys.puts("Home page: "); + } + + +} + +// Exports helper functions +for (var h in lessc_helper) { exports[h] = lessc_helper[h] } diff --git a/enyo/tools/minifier/node_modules/less/lib/less/parser.js b/enyo/tools/minifier/node_modules/less/lib/less/parser.js new file mode 100644 index 0000000..6bb90cd --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/parser.js @@ -0,0 +1,1445 @@ +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = path in that.files; + + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + } + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { + e = new(tree.Paren)(v); + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ + loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + diff --git a/enyo/tools/minifier/node_modules/less/lib/less/rhino.js b/enyo/tools/minifier/node_modules/less/lib/less/rhino.js new file mode 100644 index 0000000..9bfe8f4 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/rhino.js @@ -0,0 +1,123 @@ +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, sheet, { local: false, lastModified: 0, remaining: remaining }); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree.js b/enyo/tools/minifier/node_modules/less/lib/less/tree.js new file mode 100644 index 0000000..7038ecc --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree.js @@ -0,0 +1,43 @@ +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js new file mode 100644 index 0000000..139ae92 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js @@ -0,0 +1,17 @@ +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js new file mode 100644 index 0000000..4461490 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js @@ -0,0 +1,27 @@ +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js new file mode 100644 index 0000000..a5559ad --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js @@ -0,0 +1,19 @@ +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree')); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js new file mode 100644 index 0000000..7c2d21e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js @@ -0,0 +1,48 @@ +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js new file mode 100644 index 0000000..6adf317 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js @@ -0,0 +1,111 @@ +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js new file mode 100644 index 0000000..f4a3384 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js @@ -0,0 +1,14 @@ +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js new file mode 100644 index 0000000..6b79dc9 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js @@ -0,0 +1,42 @@ +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js new file mode 100644 index 0000000..9a6fce3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js @@ -0,0 +1,49 @@ +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js new file mode 100644 index 0000000..4d682e6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js @@ -0,0 +1,39 @@ +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js new file mode 100644 index 0000000..f02b5ab --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js @@ -0,0 +1,48 @@ +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js new file mode 100644 index 0000000..fbfa9c5 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js @@ -0,0 +1,23 @@ +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js new file mode 100644 index 0000000..7a977de --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js @@ -0,0 +1,83 @@ +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js new file mode 100644 index 0000000..772a31d --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js @@ -0,0 +1,51 @@ +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js new file mode 100644 index 0000000..701b79e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js @@ -0,0 +1,19 @@ +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js new file mode 100644 index 0000000..3bc4c54 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js @@ -0,0 +1,123 @@ +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js new file mode 100644 index 0000000..b441bf3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js @@ -0,0 +1,146 @@ +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs, arg; + + for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] + + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; + } + + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (arg && arg.value) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push((args[i] && args[i].value) || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js new file mode 100644 index 0000000..1ce22fb --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js @@ -0,0 +1,32 @@ +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js new file mode 100644 index 0000000..384a43c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js @@ -0,0 +1,16 @@ + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js new file mode 100644 index 0000000..f93dc8e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js @@ -0,0 +1,43 @@ +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js new file mode 100644 index 0000000..f7622fb --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js @@ -0,0 +1,13 @@ +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js new file mode 100644 index 0000000..9e4e54a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js @@ -0,0 +1,42 @@ +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js new file mode 100644 index 0000000..822f331 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js @@ -0,0 +1,374 @@ +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules = []; + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + rules = []; + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js new file mode 100644 index 0000000..469629c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js @@ -0,0 +1,47 @@ +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js new file mode 100644 index 0000000..e755594 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js @@ -0,0 +1,29 @@ +(function (tree) { + +tree.URL = function (val, paths) { + this.value = val; + this.paths = paths; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx); + + // Add the base path if the URL is relative and we are either + // a.) in the browser or + // b.) we have a relative file URL + if ((this.paths.length > 0) && + (typeof window !== 'undefined' || !/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0])) && + (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value))) { + var path = this.paths[0].slice(-1) === '/' ? this.paths[0] : this.paths[0] + '/'; + var v = path + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + val = new(tree.Anonymous)(v); + } + + return new(tree.URL)(val, this.paths); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js new file mode 100644 index 0000000..3c1eb29 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js @@ -0,0 +1,24 @@ +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js new file mode 100644 index 0000000..ee557e1 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js @@ -0,0 +1,26 @@ +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/package.json b/enyo/tools/minifier/node_modules/less/package.json new file mode 100644 index 0000000..7930402 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/package.json @@ -0,0 +1,17 @@ +{ + "name" : "less", + "description" : "Leaner CSS", + "url" : "http://lesscss.org", + "keywords" : ["css", "parser", "lesscss", "browser"], + "author" : "Alexis Sellier ", + "contributors" : [], + "version" : "1.3.0", + "bin" : { "lessc": "./bin/lessc" }, + "main" : "./lib/less/index", + "directories" : { "test": "./test" }, + "engines" : { "node": ">=0.4.0" }, + "devDependencies" : { "diff": "~1.0.2" }, + "scripts": { + "test": "make test" + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/colors.css b/enyo/tools/minifier/node_modules/less/test/css/colors.css new file mode 100644 index 0000000..8ff5bad --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/colors.css @@ -0,0 +1,77 @@ +#yelow #short { + color: #fea; +} +#yelow #long { + color: #ffeeaa; +} +#yelow #rgba { + color: rgba(255, 238, 170, 0.1); +} +#yelow #argb { + color: #1affeeaa; +} +#blue #short { + color: #00f; +} +#blue #long { + color: #0000ff; +} +#blue #rgba { + color: rgba(0, 0, 255, 0.1); +} +#blue #argb { + color: #1a0000ff; +} +#alpha #hsla { + color: rgba(61, 45, 41, 0.6); +} +#overflow .a { + color: #000000; +} +#overflow .b { + color: #ffffff; +} +#overflow .c { + color: #ffffff; +} +#overflow .d { + color: #00ff00; +} +#grey { + color: #c8c8c8; +} +#808080 { + color: #808080; +} +#00ff00 { + color: #00ff00; +} +.lightenblue { + color: #3333ff; +} +.darkenblue { + color: #0000cc; +} +.unknowncolors { + color: blue2; + border: 2px solid superred; +} +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha #fromvar { + opacity: 0.7; +} +#alpha #short { + opacity: 1; +} +#alpha #long { + opacity: 1; +} +#alpha #rgba { + opacity: 0.2; +} +#alpha #hsl { + opacity: 1; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/comments.css b/enyo/tools/minifier/node_modules/less/test/css/comments.css new file mode 100644 index 0000000..352dd48 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/comments.css @@ -0,0 +1,56 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ +/* + + Comment + +*/ +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ +/* @group Variables +------------------- */ +#comments { + /**/ + color: red; + /* A C-style comment */ + + background-color: orange; + font-size: 12px; + /* lost comment */ + content: "content"; + border: 1px solid black; + padding: 0; + margin: 2em; +} +/* commented out + #more-comments { + color: grey; + } +*/ +.selector, +.lots, +.comments { + color: #808080, /* blue */ #ffa500; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: 8px /* moz only with operation */; +} +#last { + color: #0000ff; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css-3.css b/enyo/tools/minifier/node_modules/less/test/css/css-3.css new file mode 100644 index 0000000..1f4da32 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/css-3.css @@ -0,0 +1,98 @@ +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} +div#id.class[a=1][b=2].class:not(1) { + color: white; +} +ul.comma > li:not(:only-child)::after { + color: white; +} +ol.comma > li:nth-last-child(2)::after { + color: white; +} +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} +a[href^="http://"] { + color: black; +} +a[href$="http://"] { + color: black; +} +form[data-disabled] { + color: black; +} +p::before { + color: black; +} +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} +@-webkit-keyframes frames { + 0% { + border: 1px; + } + 5.5% { + border: 2px; + } + 100% { + border: 3px; + } +} +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from, + to { + font-size: 12px; + } + 0%, + 100% { + font-size: 12px; + } +} +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} +@viewport { + font-size: 10px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css b/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css new file mode 100644 index 0000000..4d343aa --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css @@ -0,0 +1,24 @@ +.escape\|random\|char { + color: red; +} +.mixin\!tUp { + font-weight: bold; +} +.\34 04 { + background: red; +} +.\34 04 strong { + color: #ff00ff; + font-weight: bold; +} +.trailingTest\+ { + color: red; +} +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css.css b/enyo/tools/minifier/node_modules/less/test/css/css.css new file mode 100644 index 0000000..e0e0aa7 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/css.css @@ -0,0 +1,100 @@ +@charset "utf-8"; +div { + color: black; +} +div { + width: 99%; +} +* { + min-width: 45em; +} +h1, +h2 > a > p, +h3 { + color: none; +} +div.class { + color: blue; +} +div#id { + color: green; +} +.class#id { + color: purple; +} +.one.two.three { + color: grey; +} +@media print { + font-size: 3em; +} +@media screen { + font-size: 10px; +} +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} +a:hover, +a:link { + color: #999; +} +p, +p:first-child { + text-transform: none; +} +q:lang(no) { + quotes: none; +} +p + h1 { + font-size: 2.2em; +} +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; +} +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff)); + margin: ; + filter: alpha(opacity=100); +} +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +@font-face { + font-family: font-a; +} +@font-face { + font-family: font-b; +} +.æøå { + margin: 0; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css new file mode 100644 index 0000000..dfe93c0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css @@ -0,0 +1,39 @@ +/* line 21, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"21";}} +.tst3 { + color: grey; +} +/* line 13, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"13";}} +.test1 { + color: black; +} +/* line 4, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"4";}} +.test2 { + color: red; +} +@media all { + /* line 3, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"3";}} + .tst { + color: black; + } +} +@media all and screen { + /* line 5, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"5";}} + .tst { + color: red; + } + /* line 7, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"7";}} + .tst .tst3 { + color: white; + } +} +/* line 16, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"16";}} +.tst2 { + color: white; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css new file mode 100644 index 0000000..09e2cc0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css @@ -0,0 +1,32 @@ +/* line 21, {pathimport}test.less */ +.tst3 { + color: grey; +} +/* line 13, {path}linenumbers.less */ +.test1 { + color: black; +} +/* line 4, {path}linenumbers.less */ +.test2 { + color: red; +} +@media all { + /* line 3, {pathimport}test.less */ + .tst { + color: black; + } +} +@media all and screen { + /* line 5, {pathimport}test.less */ + .tst { + color: red; + } + /* line 7, {pathimport}test.less */ + .tst .tst3 { + color: white; + } +} +/* line 16, {pathimport}test.less */ +.tst2 { + color: white; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css new file mode 100644 index 0000000..cbcbd17 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css @@ -0,0 +1,32 @@ +@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"21";}} +.tst3 { + color: grey; +} +@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"13";}} +.test1 { + color: black; +} +@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"4";}} +.test2 { + color: red; +} +@media all { + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"3";}} + .tst { + color: black; + } +} +@media all and screen { + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"5";}} + .tst { + color: red; + } + @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"7";}} + .tst .tst3 { + color: white; + } +} +@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"16";}} +.tst2 { + color: white; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/functions.css b/enyo/tools/minifier/node_modules/less/test/css/functions.css new file mode 100644 index 0000000..a1413ef --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/functions.css @@ -0,0 +1,92 @@ +#functions { + color: #660000; + width: 16; + height: undefined("self"); + border-width: 5; + variable: 11; + background: linear-gradient(#000000, #ffffff); +} +#built-in { + escaped: -Some::weird(#thing, y); + lighten: #ffcccc; + darken: #330000; + saturate: #203c31; + desaturate: #29332f; + greyscale: #2e2e2e; + spin-p: #bf6a40; + spin-n: #bf4055; + luma-white: 100%; + luma-black: 0%; + luma-black-alpha: 0%; + luma-red: 21%; + luma-green: 72%; + luma-blue: 7%; + luma-yellow: 93%; + luma-cyan: 79%; + luma-white-alpha: 50%; + contrast-white: #000000; + contrast-black: #ffffff; + contrast-red: #ffffff; + contrast-green: #000000; + contrast-blue: #ffffff; + contrast-yellow: #000000; + contrast-cyan: #000000; + contrast-light: #111111; + contrast-dark: #eeeeee; + contrast-light-thresh: #111111; + contrast-dark-thresh: #eeeeee; + contrast-high-thresh: #eeeeee; + contrast-low-thresh: #111111; + format: "rgb(32, 128, 64)"; + format-string: "hello world"; + format-multiple: "hello earth 2"; + format-url-encode: "red is %23ff0000"; + eformat: rgb(32, 128, 64); + hue: 98; + saturation: 12%; + lightness: 95%; + red: 255; + green: 255; + blue: 255; + rounded: 11; + rounded-two: 10.67; + roundedpx: 3px; + roundedpx-three: 3.333px; + percentage: 20%; + color: #ff0011; + tint: #898989; + tint-full: #ffffff; + tint-percent: #898989; + shade: #686868; + shade-full: #000000; + shade-percent: #686868; + mix: #ff3300; + mix-0: #ffff00; + mix-100: #ff0000; + mix-weightless: #ff8000; +} +#built-in .is-a { + color: true; + color1: true; + color2: true; + keyword: true; + number: true; + string: true; + pixel: true; + percent: true; + em: true; +} +#alpha { + alpha: rgba(153, 94, 51, 0.6); +} +#blendmodes { + multiply: #ed0000; + screen: #f600f6; + overlay: #ed0000; + softlight: #ff0000; + hardlight: #0000ed; + difference: #f600f6; + exclusion: #f600f6; + average: #7b007b; + negation: #d73131; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css b/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css new file mode 100644 index 0000000..007aa53 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css @@ -0,0 +1,9 @@ +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0); +} +.evalTest1 { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=5); +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/import-once.css b/enyo/tools/minifier/node_modules/less/test/css/import-once.css new file mode 100644 index 0000000..98e2243 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/import-once.css @@ -0,0 +1,6 @@ +@import "import-test-d.css"; + +@import "../import-test-d.css"; +#import { + color: #ff0000; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/import.css b/enyo/tools/minifier/node_modules/less/test/css/import.css new file mode 100644 index 0000000..89dc162 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/import.css @@ -0,0 +1,23 @@ +@import "import-test-d.css"; + +@import url(http://fonts.googleapis.com/css?family=Open+Sans); + +@import url(something.css) screen and (color) and (max-width: 600px); +#import { + color: #ff0000; +} +.mixin { + height: 10px; + color: #ff0000; +} +#import-test { + height: 10px; + color: #ff0000; + width: 10px; + height: 30%; +} +@media screen and (max-width: 600px) { + body { + width: 100%; + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/javascript.css b/enyo/tools/minifier/node_modules/less/test/css/javascript.css new file mode 100644 index 0000000..8268ab3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/javascript.css @@ -0,0 +1,23 @@ +.eval { + js: 42; + js: 2; + js: "hello world"; + js: 1, 2, 3; + title: "string"; + ternary: true; + multiline: 2; +} +.scope { + var: 42; + escaped: 7px; +} +.vars { + width: 8; +} +.escape-interpol { + width: hello world; +} +.arrays { + ary: "1, 2, 3"; + ary1: "1, 2, 3"; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css b/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css new file mode 100644 index 0000000..1adfb8f --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css @@ -0,0 +1,3 @@ +.lazy-eval { + width: 100%; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/media.css b/enyo/tools/minifier/node_modules/less/test/css/media.css new file mode 100644 index 0000000..2be53ef --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/media.css @@ -0,0 +1,176 @@ +@media print { + .class { + color: blue; + } + .class .sub { + width: 42; + } + .top, + header > h1 { + color: #444444; + } +} +@media screen { + body { + max-width: 480; + } +} +@media all and (device-aspect-ratio: 16/9) { + body { + max-width: 800px; + } +} +@media all and (orientation: portrait) { + aside { + float: none; + } +} +@media handheld and (min-width: 42), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} +@media print { + body { + padding: 20px; + } + body header { + background-color: red; + } +} +@media print and (orientation: landscape) { + body { + margin-left: 20px; + } +} +@media screen { + .sidebar { + width: 300px; + } +} +@media screen and (orientation: landscape) { + .sidebar { + width: 500px; + } +} +@media a { + +} +@media a and b { + .first .second .third { + width: 300px; + } + .first .second .fourth { + width: 3; + } +} +@media a and b and c { + .first .second .third { + width: 500px; + } +} +@media a, b and c { + body { + width: 95%; + } +} +@media a and x, b and c and x, a and y, b and c and y { + body { + width: 100%; + } +} +.a { + background: black; +} +@media handheld { + .a { + background: white; + } +} +@media handheld and (max-width: 100px) { + .a { + background: red; + } +} +.b { + background: black; +} +@media handheld { + .b { + background: white; + } +} +@media handheld and (max-width: 200px) { + .b { + background: red; + } +} +@media only screen and (max-width: 200px) { + width: 480px; +} +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in;@top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css new file mode 100644 index 0000000..d5b67f3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css @@ -0,0 +1,74 @@ +#hidden { + color: transparent; +} +#hidden1 { + color: transparent; +} +.two-args { + color: blue; + width: 10px; + height: 99%; + border: 2px dotted #000000; +} +.one-arg { + width: 15px; + height: 49%; +} +.no-parens { + width: 5px; + height: 49%; +} +.no-args { + width: 5px; + height: 49%; +} +.var-args { + width: 45; + height: 17%; +} +.multi-mix { + width: 10px; + height: 29%; + margin: 4; + padding: 5; +} +body { + padding: 30px; + color: #ff0000; +} +.scope-mix { + width: 8; +} +.content { + width: 600px; +} +.content .column { + margin: 600px; +} +#same-var-name { + radius: 5px; +} +#var-inside { + width: 10px; +} +.arguments { + border: 1px solid #000000; + width: 1px; +} +.arguments2 { + border: 0px; + width: 0px; +} +.arguments3 { + border: 0px; + width: 0px; +} +.arguments4 { + border: 0 1 2 3 4; + rest: 1 2 3 4; + width: 0; +} +.edge-case { + border: "{"; + width: "{"; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css new file mode 100644 index 0000000..b1021b6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css @@ -0,0 +1,9 @@ +.class { + width: 99px; +} +.overwrite { + width: 99px; +} +.nested .class { + width: 5px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css new file mode 100644 index 0000000..cd94c01 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css @@ -0,0 +1,68 @@ +.light1 { + color: white; + margin: 1px; +} +.light2 { + color: black; + margin: 1px; +} +.max1 { + width: 6; +} +.max2 { + width: 8; +} +.glob1 { + margin: auto auto; +} +.ops1 { + height: gt-or-eq; + height: lt-or-eq; +} +.ops2 { + height: gt-or-eq; + height: not-eq; +} +.ops3 { + height: lt-or-eq; + height: not-eq; +} +.default1 { + content: default; +} +.test1 { + content: "true."; +} +.test2 { + content: "false."; +} +.test3 { + content: "false."; +} +.test4 { + content: "false."; +} +.test5 { + content: "false."; +} +.bool1 { + content: true and true; + content: true; + content: false, true; + content: false and true and true, true; + content: false, true and true; + content: false, false, true; + content: false, true and true and true, false; + content: not false; + content: not false and false, not false; +} +.colorguardtest { + content: is #ff0000; + content: is not #0000ff its #ff0000; + content: is not #0000ff its #800080; +} +.stringguardtest { + content: is theme1; + content: is not theme2; + content: is theme1 no quotes; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css new file mode 100644 index 0000000..2f74c64 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css @@ -0,0 +1,17 @@ +.class { + border: 1; + boxer: 1; + border: 2 !important; + boxer: 2 !important; + border: 3; + boxer: 3; + border: 4 !important; + boxer: 4 !important; + border: 5; + boxer: 5; + border: 0 !important; + boxer: 0 !important; + border: 9 !important; + border: 9; + boxer: 9; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css new file mode 100644 index 0000000..1c1afaf --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css @@ -0,0 +1,20 @@ +.named-arg { + color: blue; + width: 5px; + height: 99%; + text-align: center; +} +.class { + width: 5px; + height: 19%; +} +.named-args2 { + width: 15px; + height: 49%; + color: #646464; +} +.named-args3 { + width: 5px; + height: 29%; + color: #123456; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css new file mode 100644 index 0000000..6378c47 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css @@ -0,0 +1,14 @@ +.class .inner { + height: 300; +} +.class .inner .innest { + width: 30; + border-width: 60; +} +.class2 .inner { + height: 600; +} +.class2 .inner .innest { + width: 60; + border-width: 120; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css new file mode 100644 index 0000000..8b82833 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css @@ -0,0 +1,47 @@ +.zero { + variadic: true; + zero: 0; + one: 1; + two: 2; + three: 3; +} +.one { + variadic: true; + one: 1; + one-req: 1; + two: 2; + three: 3; +} +.two { + variadic: true; + two: 2; + three: 3; +} +.three { + variadic: true; + three-req: 3; + three: 3; +} +.left { + left: 1; +} +.right { + right: 1; +} +.border-right { + color: black; + border-right: 4px; +} +.border-left { + color: black; + border-left: 4px; +} +.only-right { + right: 33; +} +.only-left { + left: 33; +} +.left-right { + both: 330; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins.css b/enyo/tools/minifier/node_modules/less/test/css/mixins.css new file mode 100644 index 0000000..c5d3b22 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/mixins.css @@ -0,0 +1,108 @@ +.mixin { + border: 1px solid black; +} +.mixout { + border-color: orange; +} +.borders { + border-style: dashed; +} +#namespace .borders { + border-style: dotted; +} +#namespace .biohazard { + content: "death"; +} +#namespace .biohazard .man { + color: transparent; +} +#theme > .mixin { + background-color: grey; +} +#container { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +#header .milk { + color: white; + border: 1px solid black; + background-color: grey; +} +#header #cookie { + border-style: dashed; +} +#header #cookie .chips { + border-style: dotted; +} +#header #cookie .chips .calories { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +.secure-zone { + color: transparent; +} +.direct { + border-style: dotted; +} +.bo, +.bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.extended { + width: 100%; + border: 1px; + background: none; +} +.foo .bar { + width: 100%; +} +.underParents { + color: red; +} +.parent .underParents { + color: red; +} +* + h1 { + margin-top: 25px; +} +legend + h1 { + margin-top: 0; +} +h1 + * { + margin-top: 10px; +} +* + h2 { + margin-top: 20px; +} +legend + h2 { + margin-top: 0; +} +h2 + * { + margin-top: 8px; +} +* + h3 { + margin-top: 15px; +} +legend + h3 { + margin-top: 0; +} +h3 + * { + margin-top: 5px; +} +.error { + background-image: "/a.png"; + background-position: center center; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/operations.css b/enyo/tools/minifier/node_modules/less/test/css/operations.css new file mode 100644 index 0000000..fb9e0af --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/operations.css @@ -0,0 +1,49 @@ +#operations { + color: #111111; + height: 9px; + width: 3em; + substraction: 0; + division: 1; +} +#operations .spacing { + height: 9px; + width: 3em; +} +.with-variables { + height: 16em; + width: 24em; + size: 1cm; +} +.with-functions { + color: #646464; + color: #ff8080; + color: #c94a4a; +} +.negative { + height: 0px; + width: 4px; +} +.shorthands { + padding: -1px 2px 0 -4px; +} +.rem-dimensions { + font-size: 5.5rem; +} +.colors { + color: #123; + border-color: #334455; + background-color: #000000; +} +.colors .other { + color: #222222; + border-color: #222222; +} +.negations { + variable: -4px; + variable1: 0px; + variable2: 0px; + variable3: 8px; + variable4: 0px; + paren: -4px; + paren2: 16px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/parens.css b/enyo/tools/minifier/node_modules/less/test/css/parens.css new file mode 100644 index 0000000..36487fe --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/parens.css @@ -0,0 +1,20 @@ +.parens { + border: 2px solid #000000; + margin: 1px 3px 16 3; + width: 36; + padding: 2px 36px; +} +.more-parens { + padding: 8 4 4 4px; + width: 96; + height: 113; + margin: 12; +} +.nested-parens { + width: 71; + height: 6; +} +.mixed-units { + margin: 2px 4em 1 5pc; + padding: 6px 1em 2px 2; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/rulesets.css b/enyo/tools/minifier/node_modules/less/test/css/rulesets.css new file mode 100644 index 0000000..408c76a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/rulesets.css @@ -0,0 +1,33 @@ +#first > .one { + font-size: 2em; +} +#first > .one > #second .two > #deux { + width: 50%; +} +#first > .one > #second .two > #deux #third { + height: 100%; +} +#first > .one > #second .two > #deux #third:focus { + color: black; +} +#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth { + color: purple; +} +#first > .one > #second .two > #deux #fourth, +#first > .one > #second .two > #deux #five, +#first > .one > #second .two > #deux #six { + color: #110000; +} +#first > .one > #second .two > #deux #fourth .seven, +#first > .one > #second .two > #deux #five .seven, +#first > .one > #second .two > #deux #six .seven, +#first > .one > #second .two > #deux #fourth .eight > #nine, +#first > .one > #second .two > #deux #five .eight > #nine, +#first > .one > #second .two > #deux #six .eight > #nine { + border: 1px solid black; +} +#first > .one > #second .two > #deux #fourth #ten, +#first > .one > #second .two > #deux #five #ten, +#first > .one > #second .two > #deux #six #ten { + color: red; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/scope.css b/enyo/tools/minifier/node_modules/less/test/css/scope.css new file mode 100644 index 0000000..11feda8 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/scope.css @@ -0,0 +1,15 @@ +.tiny-scope { + color: #998899; +} +.scope1 { + color: #0000ff; + border-color: #000000; +} +.scope1 .scope2 { + color: #0000ff; +} +.scope1 .scope2 .scope3 { + color: #ff0000; + border-color: #000000; + background-color: #ffffff; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/selectors.css b/enyo/tools/minifier/node_modules/less/test/css/selectors.css new file mode 100644 index 0000000..ee8fe60 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/selectors.css @@ -0,0 +1,130 @@ +h1 a:hover, +h2 a:hover, +h3 a:hover, +h1 p:hover, +h2 p:hover, +h3 p:hover { + color: red; +} +#all { + color: blue; +} +#the { + color: blue; +} +#same { + color: blue; +} +ul, +li, +div, +q, +blockquote, +textarea { + margin: 0; +} +td { + margin: 0; + padding: 0; +} +td, +input { + line-height: 1em; +} +a { + color: red; +} +a:hover { + color: blue; +} +div a { + color: green; +} +p a span { + color: yellow; +} +.foo .bar .qux, +.foo .baz .qux { + display: block; +} +.qux .foo .bar, +.qux .foo .baz { + display: inline; +} +.qux.foo .bar, +.qux.foo .baz { + display: inline-block; +} +.qux .foo .bar .biz, +.qux .foo .baz .biz { + display: none; +} +.a.b.c { + color: red; +} +.c .b.a { + color: red; +} +.foo .p.bar { + color: red; +} +.foo.p.bar { + color: red; +} +.foo + .foo { + background: amber; +} +.foo + .foo { + background: amber; +} +.foo + .foo, +.foo + .bar, +.bar + .foo, +.bar + .bar { + background: amber; +} +.foo a > .foo a, +.foo a > .bar a, +.foo a > .foo b, +.foo a > .bar b, +.bar a > .foo a, +.bar a > .bar a, +.bar a > .foo b, +.bar a > .bar b, +.foo b > .foo a, +.foo b > .bar a, +.foo b > .foo b, +.foo b > .bar b, +.bar b > .foo a, +.bar b > .bar a, +.bar b > .foo b, +.bar b > .bar b { + background: amber; +} +.other ::fnord { + color: #ff0000; +} +.other::fnord { + color: #ff0000; +} +.other ::bnord { + color: #ff0000; +} +.other::bnord { + color: #ff0000; +} +.blood { + color: red; +} +.blood { + color: red; +} +.bloodred { + color: green; +} +#blood.blood.red.black { + color: black; +} +:nth-child(3):nth-child(3) { + second-use: deprecated; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/strings.css b/enyo/tools/minifier/node_modules/less/test/css/strings.css new file mode 100644 index 0000000..0c34134 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/strings.css @@ -0,0 +1,40 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: DX.Transform.MS.BS.filter(opacity=50); +} +#one-line { + image: url(http://tooks.com); +} +#crazy { + image: url(http://), "}", url("http://}"); +} +#interpolation { + url: "http://lesscss.org/dev/image.jpg"; + url2: "http://lesscss.org/image-256.jpg"; + url3: "http://lesscss.org#445566"; + url4: "http://lesscss.org/hello"; + url5: "http://lesscss.org/54.4"; +} +.mix-mul-class { + color: #0000ff; + color: #ff0000; + color: #000000; + color: #ffa500; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/variables.css b/enyo/tools/minifier/node_modules/less/test/css/variables.css new file mode 100644 index 0000000..961fe69 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/variables.css @@ -0,0 +1,27 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS", Verdana, sans-serif; + quotes: "~" "~"; +} +.redefinition { + three: 3; +} +.values { + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + url: url('Trebuchet'); + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +a:nth-child(2) { + border: 1px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/css/whitespace.css b/enyo/tools/minifier/node_modules/less/test/css/whitespace.css new file mode 100644 index 0000000..74c9b65 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/css/whitespace.css @@ -0,0 +1,42 @@ +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white ; +} +.white, +.space, +.mania { + color: white; +} +.no-semi-column { + color: #ffffff; +} +.no-semi-column { + color: white; + white-space: pre; +} +.no-semi-column { + border: 2px solid #ffffff; +} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.sel .newline_ws .tab_ws { + color: white; + background-position: 45 -23; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less-test.js b/enyo/tools/minifier/node_modules/less/test/less-test.js new file mode 100644 index 0000000..5504168 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less-test.js @@ -0,0 +1,174 @@ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var less = require('../lib/less'); +var stylize = require('../lib/less/lessc_helper').stylize; + +var oneTestOnly = process.argv[2]; + +var totalTests = 0, + failedTests = 0, + passedTests = 0; + +less.tree.functions.add = function (a, b) { + return new(less.tree.Dimension)(a.value + b.value); +}; +less.tree.functions.increment = function (a) { + return new(less.tree.Dimension)(a.value + 1); +}; +less.tree.functions._color = function (str) { + if (str.value === "evil red") { return new(less.tree.Color)("600") } +}; + +sys.puts("\n" + stylize("LESS", 'underline') + "\n"); + +runTestSet(); + +runTestSet(null, "errors/", function(name, err, compiledLess, doReplacements) { + fs.readFile(path.join('test/less/', name) + '.txt', 'utf-8', function (e, expectedErr) { + sys.print("- " + name + ": "); + expectedErr = doReplacements(expectedErr, 'test/less/errors/'); + if (!err) { + if (compiledLess) { + fail("No Error", 'red'); + } else { + fail("No Error, No Output"); + } + } else { + var errMessage = less.formatError(err); + if (errMessage === expectedErr) { + ok('OK'); + } else { + difference("FAIL", expectedErr, errMessage); + } + } + sys.puts(""); + });}, null, function(input, directory) { + return input.replace( + "{path}", path.join(process.cwd(), "/test/less/errors/")) + .replace("{pathrel}", path.join("test", "less", "errors/")) + .replace(/\r\n/g, '\n'); + }); + +runTestSet({dumpLineNumbers: 'comments'}, "debug/", null, + function(name) { return name + '-comments'; }); +runTestSet({dumpLineNumbers: 'mediaquery'}, "debug/", null, + function(name) { return name + '-mediaquery'; }); +runTestSet({dumpLineNumbers: 'all'}, "debug/", null, + function(name) { return name + '-all'; }); + +function globalReplacements(input, directory) { + return input.replace(/\{path\}/g, path.join(process.cwd(), directory)) + .replace(/\{pathimport\}/g, path.join(process.cwd(), directory + "import/")) + .replace(/\r\n/g, '\n'); +} + +function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements) { + foldername = foldername || ""; + + if(!doReplacements) + doReplacements = globalReplacements; + + fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) { + if (! /\.less/.test(file)) { return } + + var name = foldername + path.basename(file, '.less'); + + if (oneTestOnly && name !== oneTestOnly) { return; } + + totalTests++; + + toCSS(options, path.join('test/less/', foldername + file), function (err, less) { + + if (verifyFunction) { + return verifyFunction(name, err, less, doReplacements); + } + var css_name = name; + if(nameModifier) css_name=nameModifier(name); + fs.readFile(path.join('test/css', css_name) + '.css', 'utf-8', function (e, css) { + sys.print("- " + css_name + ": ") + + css = css && doReplacements(css, 'test/less/' + foldername); + if (less === css) { ok('OK'); } + else if (err) { + fail("ERROR: " + (err && err.message)); + } else { + difference("FAIL", css, less); + } + sys.puts(""); + }); + }); + }); +} + +function diff(left, right) { + sys.puts(""); + require('diff').diffLines(left, right).forEach(function(item) { + if(item.added || item.removed) { + sys.print(stylize(item.value, item.added ? 'green' : 'red')); + } else { + sys.print(item.value); + } + }); +} + +function fail(msg) { + sys.print(stylize(msg, 'red')); + failedTests++; + endTest(); +} + +function difference(msg, left, right) { + sys.print(stylize(msg, 'yellow')); + failedTests++; + + diff(left, right); + endTest(); +} + +function ok(msg) { + sys.print(stylize(msg, 'green')); + passedTests++; + endTest(); +} + +function endTest() { + if (failedTests + passedTests === totalTests) { + sys.puts(""); + sys.puts(""); + if (failedTests > 0) { + sys.print(failedTests); + sys.print(stylize(" Failed", "red")); + sys.print(", " + passedTests + " passed"); + } else { + sys.print(stylize("All Passed ", "green")); + sys.print(passedTests + " run"); + } + } +} + +function toCSS(options, path, callback) { + var tree, css; + options = options || {}; + fs.readFile(path, 'utf-8', function (e, str) { + if (e) { return callback(e) } + + options.paths = [require('path').dirname(path)]; + options.filename = require('path').resolve(process.cwd(), path); + options.optimization = options.optimization || 0; + + new(less.Parser)(options).parse(str, function (err, tree) { + if (err) { + callback(err); + } else { + try { + css = tree.toCSS(); + callback(null, css); + } catch (e) { + callback(e); + } + } + }); + }); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/colors.less b/enyo/tools/minifier/node_modules/less/test/less/colors.less new file mode 100644 index 0000000..d8038de --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/colors.less @@ -0,0 +1,88 @@ +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } + #argb { + color: argb(rgba(255, 238, 170, 0.1)); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } + #argb { + color: argb(rgba(0, 0, 255, 0.1)); + } +} + +#alpha #hsla { + color: hsla(11, 20%, 20%, 0.6); +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} + +.lightenblue { + color: lighten(blue, 10%); +} + +.darkenblue { + color: darken(blue, 10%); +} + +.unknowncolors { + color: blue2; + border: 2px solid superred; +} + +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha { + @colorvar: rgba(150, 200, 150, 0.7); + #fromvar { + opacity: alpha(@colorvar); + } + #short { + opacity: alpha(#aaa); + } + #long { + opacity: alpha(#bababa); + } + #rgba { + opacity: alpha(rgba(50, 120, 95, 0.2)); + } + #hsl { + opacity: alpha(hsl(120, 100%, 50%)); + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/comments.less b/enyo/tools/minifier/node_modules/less/test/less/comments.less new file mode 100644 index 0000000..1b5c63e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/comments.less @@ -0,0 +1,65 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; // }{ '" + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +.selector /* .with */, .lots, /* of */ .comments { + color: grey, /* blue */ orange; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: 2px * 4 /* moz only with operation */; +} + +#last { color: blue } +// diff --git a/enyo/tools/minifier/node_modules/less/test/less/css-3.less b/enyo/tools/minifier/node_modules/less/test/less/css-3.less new file mode 100644 index 0000000..0d72d18 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/css-3.less @@ -0,0 +1,108 @@ +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} + +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} + +@-webkit-keyframes frames { + 0% { border: 1px } + 5.5% { border: 2px } + 100% { border: 3px } +} + +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from,to { + font-size: 12px; + } + 0%,100% { + font-size: 12px; + } +} + +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} + +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} + +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} + +@viewport { + font-size: 10px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less b/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less new file mode 100644 index 0000000..6a4b283 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less @@ -0,0 +1,33 @@ +@ugly: fuchsia; + +.escape\|random\|char { + color: red; +} + +.mixin\!tUp { + font-weight: bold; +} + +// class="404" +.\34 04 { + background: red; + + strong { + color: @ugly; + .mixin\!tUp; + } +} + +.trailingTest\+ { + color: red; +} + +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} + +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/css.less b/enyo/tools/minifier/node_modules/less/test/less/css.less new file mode 100644 index 0000000..2340f6e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/css.less @@ -0,0 +1,115 @@ +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; + filter: alpha(opacity=100); +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.def-font(@name) { + @font-face { + font-family: @name + } +} + +.def-font(font-a); +.def-font(font-b); + +.æøå { + margin: 0; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less b/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less new file mode 100644 index 0000000..fe4f4f2 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less @@ -0,0 +1,23 @@ +.mixin_import1() { + @media all { + .tst { + color: black; + @media screen { + color: red; + .tst3 { + color: white; + } + } + } + } +} + +.mixin_import2() { + .tst2 { + color: white; + } +} + +.tst3 { + color: grey; +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less b/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less new file mode 100644 index 0000000..dbf9770 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less @@ -0,0 +1,21 @@ +@import "import/test.less"; + +.start() { + .test2 { + color: red; + } +} + +.mix() { + color: black; +} + +.test1 { + .mix(); +} + +.start(); + +.mixin_import1(); + +.mixin_import2(); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less new file mode 100644 index 0000000..a7d2639 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less @@ -0,0 +1 @@ +#gaga /* Comment */ span { color: red } \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt new file mode 100644 index 0000000..571462f --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt @@ -0,0 +1,2 @@ +ParseError: Syntax Error on line 1 in {path}comment-in-selector.less:1:20 +1 #gaga /* Comment */ span { color: red } diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less new file mode 100644 index 0000000..b740c11 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less @@ -0,0 +1 @@ +@import "file-does-not-exist.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt new file mode 100644 index 0000000..2502e09 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt @@ -0,0 +1,3 @@ +FileError: 'file-does-not-exist.less' wasn't found. + in {path}import-missing.less:1:0 +1 @import "file-does-not-exist.less"; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less new file mode 100644 index 0000000..bf2c7f6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less @@ -0,0 +1 @@ +@import "this-statement-is-invalid.less" \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt new file mode 100644 index 0000000..60ae3f3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt @@ -0,0 +1,2 @@ +ParseError: Syntax Error on line 1 in {path}import-no-semi.less:1:0 +1 @import "this-statement-is-invalid.less" diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less new file mode 100644 index 0000000..4280673 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less @@ -0,0 +1 @@ +@import "imports/import-subfolder1.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt new file mode 100644 index 0000000..7bfd3b3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {pathrel}mixin-not-defined.less:11:0 +10 +11 .mixin-not-defined(); diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less new file mode 100644 index 0000000..a6b9b9c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less @@ -0,0 +1 @@ +@import "imports/import-subfolder2.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt new file mode 100644 index 0000000..1c59d17 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt @@ -0,0 +1,2 @@ +ParseError: Syntax Error on line 1 in {pathrel}parse-error-curly-bracket.less:1:0 +1 }} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less new file mode 100644 index 0000000..24ec053 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less @@ -0,0 +1 @@ +@import "subfolder/mixin-not-defined.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less new file mode 100644 index 0000000..6058ad1 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less @@ -0,0 +1 @@ +@import "subfolder/parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less new file mode 100644 index 0000000..2bb2d09 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less @@ -0,0 +1 @@ +@import "../../mixin-not-defined.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less new file mode 100644 index 0000000..f37fa9d --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less @@ -0,0 +1 @@ +@import "../../parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less new file mode 100644 index 0000000..9cffb9f --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less @@ -0,0 +1,3 @@ +.scope { + var: `this.foo.toJS()`; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt new file mode 100644 index 0000000..16dc9b7 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt @@ -0,0 +1,4 @@ +SyntaxError: JavaScript evaluation error: 'TypeError: Cannot call method 'toJS' of undefined' in {path}javascript-error.less:2:26 +1 .scope { +2 var: `this.foo.toJS()`; +3 } diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less new file mode 100644 index 0000000..e2dad5c --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less @@ -0,0 +1,11 @@ + +.error-is-further-on() { +} + +.pad-here-to-reproduce-error-in() { +} + +.the-import-subfolder-test() { +} + +.mixin-not-defined(); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt new file mode 100644 index 0000000..f45de6a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less:11:0 +10 +11 .mixin-not-defined(); diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less new file mode 100644 index 0000000..a2950a1 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less @@ -0,0 +1 @@ +}} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt new file mode 100644 index 0000000..f472c17 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt @@ -0,0 +1,2 @@ +ParseError: Syntax Error on line 1 in {path}parse-error-curly-bracket.less:1:0 +1 }} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less new file mode 100644 index 0000000..144a6ed --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less @@ -0,0 +1,2 @@ +body { + background-color: #fff; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt new file mode 100644 index 0000000..ea47da3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt @@ -0,0 +1,2 @@ +ParseError: missing closing `}` in {path}parse-error-missing-bracket.less:3:1 +2 background-color: #fff; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less new file mode 100644 index 0000000..51bf6e3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less @@ -0,0 +1,3 @@ +.test { + display/*/: block; /*sorry for IE5*/ +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt new file mode 100644 index 0000000..c809140 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt @@ -0,0 +1,4 @@ +ParseError: Syntax Error on line 2 in {path}property-ie5-hack.less:2:2 +1 .test { +2 display/*/: block; /*sorry for IE5*/ +3 } diff --git a/enyo/tools/minifier/node_modules/less/test/less/functions.less b/enyo/tools/minifier/node_modules/less/test/less/functions.less new file mode 100644 index 0000000..6afed38 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/functions.less @@ -0,0 +1,101 @@ +#functions { + @var: 10; + @colors: #000, #fff; + color: _color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); + background: linear-gradient(@colors); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 40%); + darken: darken(#ff0000, 40%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + spin-p: spin(hsl(340, 50%, 50%), 40); + spin-n: spin(hsl(30, 50%, 50%), -40); + luma-white: luma(#fff); + luma-black: luma(#000); + luma-black-alpha: luma(rgba(0,0,0,0.5)); + luma-red: luma(#ff0000); + luma-green: luma(#00ff00); + luma-blue: luma(#0000ff); + luma-yellow: luma(#ffff00); + luma-cyan: luma(#00ffff); + luma-white-alpha: luma(rgba(255,255,255,0.5)); + contrast-white: contrast(#fff); + contrast-black: contrast(#000); + contrast-red: contrast(#ff0000); + contrast-green: contrast(#00ff00); + contrast-blue: contrast(#0000ff); + contrast-yellow: contrast(#ffff00); + contrast-cyan: contrast(#00ffff); + contrast-light: contrast(#fff, #111111, #eeeeee); + contrast-dark: contrast(#000, #111111, #eeeeee); + contrast-light-thresh: contrast(#fff, #111111, #eeeeee, 0.5); + contrast-dark-thresh: contrast(#000, #111111, #eeeeee, 0.5); + contrast-high-thresh: contrast(#555, #111111, #eeeeee, 0.6); + contrast-low-thresh: contrast(#555, #111111, #eeeeee, 0.1); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + format-multiple: %("hello %s %d", "earth", 2); + format-url-encode: %('red is %A', #ff0000); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); + + hue: hue(hsl(98, 12%, 95%)); + saturation: saturation(hsl(98, 12%, 95%)); + lightness: lightness(hsl(98, 12%, 95%)); + red: red(#f00); + green: green(#0f0); + blue: blue(#00f); + rounded: round(@r/3); + rounded-two: round(@r/3, 2); + roundedpx: round(10px / 3); + roundedpx-three: round(10px / 3, 3); + percentage: percentage(10px / 50); + color: color("#ff0011"); + tint: tint(#777777, 13); + tint-full: tint(#777777, 100); + tint-percent: tint(#777777, 13%); + shade: shade(#777777, 13); + shade-full: shade(#777777, 100); + shade-percent: shade(#777777, 13%); + + mix: mix(#ff0000, #ffff00, 80); + mix-0: mix(#ff0000, #ffff00, 0); + mix-100: mix(#ff0000, #ffff00, 100); + mix-weightless: mix(#ff0000, #ffff00); + + .is-a { + color: iscolor(#ddd); + color1: iscolor(red); + color2: iscolor(rgb(0, 0, 0)); + keyword: iskeyword(hello); + number: isnumber(32); + string: isstring("hello"); + pixel: ispixel(32px); + percent: ispercentage(32%); + em: isem(32em); + } +} + +#alpha { + alpha: darken(hsla(25, 50%, 50%, 0.6), 10%); +} + +#blendmodes { + multiply: multiply(#f60000, #f60000); + screen: screen(#f60000, #0000f6); + overlay: overlay(#f60000, #0000f6); + softlight: softlight(#f60000, #ffffff); + hardlight: hardlight(#f60000, #0000f6); + difference: difference(#f60000, #0000f6); + exclusion: exclusion(#f60000, #0000f6); + average: average(#f60000, #0000f6); + negation: negation(#f60000, #313131); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less b/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less new file mode 100644 index 0000000..3350b65 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less @@ -0,0 +1,15 @@ +@fat: 0; +@cloudhead: "#000000"; + +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat); +} +.evalTest(@arg) { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg); +} +.evalTest1 { + .evalTest(30); + .evalTest(5); +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import-once.less b/enyo/tools/minifier/node_modules/less/test/less/import-once.less new file mode 100644 index 0000000..f2f6362 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import-once.less @@ -0,0 +1,3 @@ +@import-once "import/import-once-test-c"; +@import-once "import/import-once-test-c"; +@import-once "import/deeper/import-once-test-a"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import.less b/enyo/tools/minifier/node_modules/less/test/less/import.less new file mode 100644 index 0000000..13ed5c5 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import.less @@ -0,0 +1,11 @@ +@import url("import/import-test-a.less"); +@import url(http://fonts.googleapis.com/css?family=Open+Sans); + +@import url(something.css) screen and (color) and (max-width: 600px); + +#import-test { + .mixin; + width: 10px; + height: @a + 10%; +} +@import "import/import-test-e" screen and (max-width: 600px); diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less b/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less new file mode 100644 index 0000000..2c399fa --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less @@ -0,0 +1 @@ +@import-once "../import-test-d.css"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less new file mode 100644 index 0000000..838fabc --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less @@ -0,0 +1,7 @@ + +@import-once "import-test-d.css"; +@c: red; + +#import { + color: @c; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less new file mode 100644 index 0000000..7409d07 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less @@ -0,0 +1,2 @@ +@import "import-test-b.less"; +@a: 20%; diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less new file mode 100644 index 0000000..ce2d35a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less @@ -0,0 +1,8 @@ +@import "import-test-c"; + +@b: 100%; + +.mixin { + height: 10px; + color: @c; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less new file mode 100644 index 0000000..111266b --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less @@ -0,0 +1,7 @@ + +@import "import-test-d.css"; +@c: red; + +#import { + color: @c; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css new file mode 100644 index 0000000..30575f0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css @@ -0,0 +1 @@ +#css { color: yellow; } diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less new file mode 100644 index 0000000..98b84b0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less @@ -0,0 +1,2 @@ + +body { width: 100% } diff --git a/enyo/tools/minifier/node_modules/less/test/less/javascript.less b/enyo/tools/minifier/node_modules/less/test/less/javascript.less new file mode 100644 index 0000000..b76859e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/javascript.less @@ -0,0 +1,29 @@ +.eval { + js: `42`; + js: `1 + 1`; + js: `"hello world"`; + js: `[1, 2, 3]`; + title: `typeof process.title`; + ternary: `(1 + 1 == 2 ? true : false)`; + multiline: `(function(){var x = 1 + 1; + return x})()`; +} +.scope { + @foo: 42; + var: `this.foo.toJS()`; + escaped: ~`2 + 5 + 'px'`; +} +.vars { + @var: `4 + 4`; + width: @var; +} +.escape-interpol { + @world: "world"; + width: ~`"hello" + " " + @{world}`; +} +.arrays { + @ary: 1, 2, 3; + @ary2: 1 2 3; + ary: `@{ary}.join(', ')`; + ary1: `@{ary2}.join(', ')`; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less b/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less new file mode 100644 index 0000000..72b3fd4 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less @@ -0,0 +1,6 @@ +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/media.less b/enyo/tools/minifier/node_modules/less/test/less/media.less new file mode 100644 index 0000000..3dc1aab --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/media.less @@ -0,0 +1,179 @@ + +// For now, variables can't be declared inside @media blocks. + +@var: 42; + +@media print { + .class { + color: blue; + .sub { + width: @var; + } + } + .top, header > h1 { + color: #222 * 2; + } +} + +@media screen { + @base: 8; + body { max-width: @base * 60; } +} + +@media all and (device-aspect-ratio: 16/9) { + body { max-width: 800px; } +} + +@media all and (orientation:portrait) { + aside { float: none; } +} + +@media handheld and (min-width: @var), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} + +body { + @media print { + padding: 20px; + + header { + background-color: red; + } + + @media (orientation:landscape) { + margin-left: 20px; + } + } +} + +@media screen { + .sidebar { + width: 300px; + @media (orientation: landscape) { + width: 500px; + } + } +} + +@media a { + .first { + @media b { + .second { + .third { + width: 300px; + @media c { + width: 500px; + } + } + .fourth { + width: 3; + } + } + } + } +} + +body { + @media a, b and c { + width: 95%; + + @media x, y { + width: 100%; + } + } +} + +.mediaMixin(@fallback: 200px) { + background: black; + + @media handheld { + background: white; + + @media (max-width: @fallback) { + background: red; + } + } +} + +.a { + .mediaMixin(100px); +} + +.b { + .mediaMixin(); +} +@smartphone: ~"only screen and (max-width: 200px)"; +@media @smartphone { + width: 480px; +} + +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in; + @top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} + +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less new file mode 100644 index 0000000..ea43a0a --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less @@ -0,0 +1,130 @@ +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; // asd +} + +#hidden { + .hidden; +} + +#hidden1 { + .hidden(); +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } + +.mixin-arguments (@width: 0px, ...) { + border: @arguments; + width: @width; +} + +.arguments { + .mixin-arguments(1px, solid, black); +} +.arguments2 { + .mixin-arguments(); +} +.arguments3 { + .mixin-arguments; +} + +.mixin-arguments2 (@width, @rest...) { + border: @arguments; + rest: @rest; + width: @width; +} +.arguments4 { + .mixin-arguments2(0, 1, 2, 3, 4); +} + +// Edge cases + +.edge-case { + .mixin-arguments("{"); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less new file mode 100644 index 0000000..01251d2 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less @@ -0,0 +1,26 @@ +.scope { + @var: 99px; + .mixin () { + width: @var; + } +} + +.class { + .scope > .mixin; +} + +.overwrite { + @var: 0px; + .scope > .mixin; +} + +.nested { + @var: 5px; + .mixin () { + width: @var; + } + .class { + @var: 10px; + .mixin; + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less new file mode 100644 index 0000000..3e27c26 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less @@ -0,0 +1,113 @@ + +// Stacking, functions.. + +.light (@a) when (lightness(@a) > 50%) { + color: white; +} +.light (@a) when (lightness(@a) < 50%) { + color: black; +} +.light (@a) { + margin: 1px; +} + +.light1 { .light(#ddd) } +.light2 { .light(#444) } + +// Arguments against each other + +.max (@a, @b) when (@a > @b) { + width: @a; +} +.max (@a, @b) when (@a < @b) { + width: @b; +} + +.max1 { .max(3, 6) } +.max2 { .max(8, 1) } + +// Globals inside guards + +@g: auto; + +.glob (@a) when (@a = @g) { + margin: @a @g; +} +.glob1 { .glob(auto) } + +// Other operators + +.ops (@a) when (@a >= 0) { + height: gt-or-eq; +} +.ops (@a) when (@a =< 0) { + height: lt-or-eq; +} +.ops (@a) when not(@a = 0) { + height: not-eq; +} +.ops1 { .ops(0) } +.ops2 { .ops(1) } +.ops3 { .ops(-1) } + +// Scope and default values + +@a: auto; + +.default (@a: inherit) when (@a = inherit) { + content: default; +} +.default1 { .default } + +// true & false keywords +.test (@a) when (@a) { + content: "true."; +} +.test (@a) when not (@a) { + content: "false."; +} + +.test1 { .test(true) } +.test2 { .test(false) } +.test3 { .test(1) } +.test4 { .test(boo) } +.test5 { .test("true") } + +// Boolean expressions + +.bool () when (true) and (false) { content: true and false } // FALSE +.bool () when (true) and (true) { content: true and true } // TRUE +.bool () when (true) { content: true } // TRUE +.bool () when (false) and (false) { content: true } // FALSE +.bool () when (false), (true) { content: false, true } // TRUE +.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE +.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE +.bool () when (false), (true) and (true) { content: false, true and true } // TRUE +.bool () when (false), (false), (true) { content: false, false, true } // TRUE +.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE +.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE +.bool () when not (false) { content: not false } +.bool () when not (true) and not (false) { content: not true and not false } +.bool () when not (true) and not (true) { content: not true and not true } +.bool () when not (false) and (false), not (false) { content: not false and false, not false } + +.bool1 { .bool } + +.colorguard(@col) when (@col = red) { content: is @col; } +.colorguard(@col) when not (blue = @col) { content: is not blue its @col; } +.colorguard(@col) {} +.colorguardtest { + .colorguard(red); + .colorguard(blue); + .colorguard(purple); +} + +.stringguard(@str) when (@str = "theme1") { content: is theme1; } +.stringguard(@str) when not ("theme2" = @str) { content: is not theme2; } +.stringguard(@str) when (~"theme1" = @str) { content: is theme1 no quotes; } +.stringguard(@str) {} +.stringguardtest { + .stringguard("theme1"); + .stringguard("theme2"); + .stringguard(theme1); +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less new file mode 100644 index 0000000..790a4d6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less @@ -0,0 +1,18 @@ + +.mixin (9) { + border: 9 !important; +} +.mixin (@a: 0) { + border: @a; + boxer: @a; +} + +.class { + .mixin(1); + .mixin(2) !important; + .mixin(3); + .mixin(4) !important; + .mixin(5); + .mixin !important; + .mixin(9); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less new file mode 100644 index 0000000..57b07d0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less @@ -0,0 +1,31 @@ +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} +.mixin (@a: 1px, @b: 50%) when (@b > 75%){ + text-align: center; +} + +.named-arg { + color: blue; + .mixin(@b: 100%); +} + +.class { + @var: 20%; + .mixin(@b: @var); +} + +.mixin2 (@a: 1px, @b: 50%, @c: 50) { + width: @a * 5; + height: @b - 1%; + color: #000000 + @c; +} + +.named-args2 { + .mixin2(3px, @c: 100); +} + +.named-args3 { + .mixin2(@b: 30%, @c: #123456); +} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less new file mode 100644 index 0000000..d086279 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less @@ -0,0 +1,22 @@ +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} + +.class2 { + .mix(60); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less new file mode 100644 index 0000000..b2121e9 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less @@ -0,0 +1,99 @@ +.mixin (...) { + variadic: true; +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: @r * 10; +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins.less b/enyo/tools/minifier/node_modules/less/test/less/mixins.less new file mode 100644 index 0000000..7158c2e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/mixins.less @@ -0,0 +1,93 @@ +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} + +.bo, .bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.extended { + .bo; + .jo.ki; +} +.foo .bar { + .bar; +} +.has_parents() { + & .underParents { + color: red; + } +} +.has_parents(); +.parent { + .has_parents(); +} +.margin_between(@above, @below) { + * + & { margin-top: @above; } + legend + & { margin-top: 0; } + & + * { margin-top: @below; } +} +h1 { .margin_between(25px, 10px); } +h2 { .margin_between(20px, 8px); } +h3 { .margin_between(15px, 5px); } + +.mixin_def(@url, @position){ + background-image: @url; + background-position: @position; +} +.error{ + @s: "/"; + .mixin_def( "@{s}a.png", center center); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/operations.less b/enyo/tools/minifier/node_modules/less/test/less/operations.less new file mode 100644 index 0000000..46b0aa3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/operations.less @@ -0,0 +1,62 @@ +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + .spacing { + height: 10px / 2px+6px-1px*2; + width: 2 * 4-5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +.with-functions { + color: rgb(200, 200, 200) / 2; + color: 2 * hsl(0, 50%, 50%); + color: rgb(10, 10, 10) + hsl(0, 50%, 50%); +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.rem-dimensions { + font-size: 20rem / 5 + 1.5rem; // 5.5rem +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} + +.negations { + @var: 4px; + variable: -@var; // 4 + variable1: -@var + @var; // 0 + variable2: @var + -@var; // 0 + variable3: @var - -@var; // 8 + variable4: -@var - -@var; // 0 + paren: -(@var); // -4px + paren2: -(2 + 2) * -@var; // 16 +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/parens.less b/enyo/tools/minifier/node_modules/less/test/less/parens.less new file mode 100644 index 0000000..e020c7e --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/parens.less @@ -0,0 +1,26 @@ +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6px * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width: (@var * @var) * 6; + height: (7 * 7) + (8 * 8); + margin: 4 * (5 + 5) / 2 - (@var * 2); + //margin: (6 * 6)px; +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2+3)*(2+3) / (9-4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/rulesets.less b/enyo/tools/minifier/node_modules/less/test/less/rulesets.less new file mode 100644 index 0000000..e81192d --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/rulesets.less @@ -0,0 +1,30 @@ +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/scope.less b/enyo/tools/minifier/node_modules/less/test/less/scope.less new file mode 100644 index 0000000..da66462 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/scope.less @@ -0,0 +1,32 @@ +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} + +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/selectors.less b/enyo/tools/minifier/node_modules/less/test/less/selectors.less new file mode 100644 index 0000000..a66b598 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/selectors.less @@ -0,0 +1,131 @@ +h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} + +a { + color: red; + + &:hover { color: blue; } + + div & { color: green; } + + p & span { color: yellow; } +} + +.foo { + .bar, .baz { + & .qux { + display: block; + } + .qux & { + display: inline; + } + .qux& { + display: inline-block; + } + .qux & .biz { + display: none; + } + } +} + +.b { + &.c { + .a& { + color: red; + } + } +} + +.b { + .c & { + &.a { + color: red; + } + } +} + +.p { + .foo &.bar { + color: red; + } +} + +.p { + .foo&.bar { + color: red; + } +} + +.foo { + .foo + & { + background: amber; + } + & + & { + background: amber; + } +} + +.foo, .bar { + & + & { + background: amber; + } +} + +.foo, .bar { + a, b { + & > & { + background: amber; + } + } +} + +.other ::fnord { color: red } +.other::fnord { color: red } +.other { + ::bnord {color: red } + &::bnord {color: red } +} +// selector interpolation - deprecated +@theme: blood; +(~".@{theme}") { + color: red; +} +// selector interpolation - new format +@selector: ~".@{theme}"; +@{selector} { + color:red; +} +@{selector}red { + color: green; +} +.red { + #@{theme}.@{theme}&.black { + color:black; + } +} +@num: 3; +:nth-child(@{num}):nth-child(@num) { + second-use: deprecated; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/strings.less b/enyo/tools/minifier/node_modules/less/test/less/strings.less new file mode 100644 index 0000000..32fad72 --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/strings.less @@ -0,0 +1,51 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: ~"DX.Transform.MS.BS.filter(opacity=50)"; +} +#one-line { image: url(http://tooks.com) } +#crazy { image: url(http://), "}", url("http://}") } +#interpolation { + @var: '/dev'; + url: "http://lesscss.org@{var}/image.jpg"; + + @var2: 256; + url2: "http://lesscss.org/image-@{var2}.jpg"; + + @var3: #456; + url3: "http://lesscss.org@{var3}"; + + @var4: hello; + url4: "http://lesscss.org/@{var4}"; + + @var5: 54.4px; + url5: "http://lesscss.org/@{var5}"; +} + +// multiple calls with string interpolation + +.mix-mul (@a: green) { + color: ~"@{a}"; +} +.mix-mul-class { + .mix-mul(blue); + .mix-mul(red); + .mix-mul(black); + .mix-mul(orange); +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/variables.less b/enyo/tools/minifier/node_modules/less/test/less/variables.less new file mode 100644 index 0000000..66ab4ef --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/variables.less @@ -0,0 +1,54 @@ +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + @multi: 'A', B, C; + font-family: @a, @a, @a; + color: @c !important; + url: url(@a); + multi: something @multi, @a; +} + +.variable-names { + @var: 'hello'; + @name: 'var'; + name: @@name; +} +.alpha { + @var: 42; + filter: alpha(opacity=@var); +} + +a:nth-child(@a) { + border: 1px; +} diff --git a/enyo/tools/minifier/node_modules/less/test/less/whitespace.less b/enyo/tools/minifier/node_modules/less/test/less/whitespace.less new file mode 100644 index 0000000..ab4804d --- /dev/null +++ b/enyo/tools/minifier/node_modules/less/test/less/whitespace.less @@ -0,0 +1,44 @@ + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +.sel +.newline_ws .tab_ws { +color: +white; +background-position: 45 +-23; +} diff --git a/enyo/tools/minifier/node_modules/uglify-js/.npmignore b/enyo/tools/minifier/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..83c3dac --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/.npmignore @@ -0,0 +1,6 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* +node_modules/ +npm-debug.log diff --git a/enyo/tools/minifier/node_modules/uglify-js/README.html b/enyo/tools/minifier/node_modules/uglify-js/README.html new file mode 100644 index 0000000..5f37ac0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/README.html @@ -0,0 +1,981 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
    + +
    + +
    +

    UglifyJS – a JavaScript parser/compressor/beautifier

    + + + + +
    +

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    +
    + + +

    +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

    +

    +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

    +

    +( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

    +

    +The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

    +
      +
    • ability to re-generate JavaScript code from the AST. Optionally + indented—you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +
    • +
    • shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with eval() calls or with{} statements. In short, if eval() or + with{} are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +
    • +
    • various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + +
        +
      • foo["bar"] ==> foo.bar + +
      • +
      • remove block brackets {} + +
      • +
      • join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + +
      • +
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + +
      • +
      • consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + +
      • +
      • various optimizations for IF statements: + +
          +
        • if (foo) bar(); else baz(); ==> foo?bar():baz(); +
        • +
        • if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
        • +
        • if (foo) bar(); ==> foo&&bar(); +
        • +
        • if (!foo) bar(); ==> foo||bar(); +
        • +
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
        • +
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
        • +
        + +
      • +
      • remove some unreachable code and warn about it (code that follows a + return, throw, break or continue statement, except + function/variable declarations). + +
      • +
      • act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.1 Unsafe transformations

    +
    + + +

    +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

    + +
    + +
    +

    1.1.1 Calls involving the global Array constructor

    +
    + + +

    +The following transformations occur: +

    + + + +
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +Array(a, b, c)         => [a,b,c]
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
    +
    + + +

    +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

    +

    +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

    + + + +
    // case 1.  globally declared variable
    +  var Array;
    +  new Array(1, 2, 3);
    +  Array(a, b);
    +
    +  // or (can be declared later)
    +  new Array(1, 2, 3);
    +  var Array;
    +
    +  // or (can be a function)
    +  new Array(1, 2, 3);
    +  function Array() { ... }
    +
    +// case 2.  declared in a function
    +  (function(){
    +    a = new Array(1, 2, 3);
    +    b = Array(5, 6);
    +    var Array;
    +  })();
    +
    +  // or
    +  (function(Array){
    +    return Array(5, 6, 7);
    +  })();
    +
    +  // or
    +  (function(){
    +    return new Array(1, 2, 3, 4);
    +    function Array() { ... }
    +  })();
    +
    +  // etc.
    +
    + + +
    + +
    + +
    +

    1.1.2 obj.toString() ==> obj+“”

    +
    + + +
    +
    + +
    + +
    +

    1.2 Install (NPM)

    +
    + + +

    +UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

    +
    + +
    + +
    +

    1.3 Install latest code from GitHub

    +
    + + + + + +
    ## clone the repository
    +mkdir -p /where/you/wanna/put/it
    +cd /where/you/wanna/put/it
    +git clone git://github.com/mishoo/UglifyJS.git
    +
    +## make the module available to Node
    +mkdir -p ~/.node_libraries/
    +cd ~/.node_libraries/
    +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
    +
    +## and if you want the CLI script too:
    +mkdir -p ~/bin
    +cd ~/bin
    +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
    +  # (then add ~/bin to your $PATH if it's not there already)
    +
    + + +
    + +
    + +
    +

    1.4 Usage

    +
    + + +

    +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

    + + + +
    uglifyjs [ options... ] [ filename ]
    +
    + + +

    +filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

    +

    +Supported options: +

    +
      +
    • -b or --beautify — output indented code; when passed, additional + options control the beautifier: + +
        +
      • -i N or --indent N — indentation level (number of spaces) + +
      • +
      • -q or --quote-keys — quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +
      • +
      + +
    • +
    • --ascii — pass this argument to encode non-ASCII characters as + \uXXXX sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +
    • +
    • -nm or --no-mangle — don't mangle names. + +
    • +
    • -nmf or --no-mangle-functions – in case you want to mangle variable + names, but not touch function names. + +
    • +
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various + optimizations that result in smaller, less readable code). + +
    • +
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too + (by default we don't do this). + +
    • +
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass + --no-squeeze) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass --no-seqs to disable it. + +
    • +
    • --no-dead-code — by default, UglifyJS will remove code that is + obviously unreachable (code that follows a return, throw, break or + continue statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +
    • +
    • -nc or --no-copyright — by default, uglifyjs will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +
    • +
    • -o filename or --output filename — put the result in filename. If + this isn't given, the result goes to standard output (or see next one). + +
    • +
    • --overwrite — if the code is read from a file (not from STDIN) and you + pass --overwrite then the output will be written in the same file. + +
    • +
    • --ast — pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +
    • +
    • -v or --verbose — output some notes on STDERR (for now just how long + each operation takes). + +
    • +
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value true, or you can specify a numeric value (such as + 1024), a quoted string value (such as ="object"= or + ='https://github.com'), or the name of another symbol or keyword (such as =null or document). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of conditional compilation + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + --define-from-module more suitable for use. + +
    • +
    • -define-from-module SOMEMODULE — will load the named module (as + per the NodeJS require() function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the --define option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of --define + options. + +
    • +
    • --unsafe — enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + +
        +
      • foo.toString() ==> foo+"" +
      • +
      • new Array(x,…) ==> [x,…] +
      • +
      • new Array(x) ==> Array(x) + +
      • +
      + +
    • +
    • --max-line-len (default 32K characters) — add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass –max-line-len 0 to disable this + safety feature. + +
    • +
    • --reserved-names — some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names require and $super + intact you'd specify –reserved-names "require,$super". + +
    • +
    • --inline-script – when you want to include the output literally in an + HTML <script> tag you can use this option to prevent </script from + showing up in the output. + +
    • +
    • --lift-vars – when you pass this, UglifyJS will apply the following + transformations (see the notes in API, ast_lift_variables): + +
        +
      • put all var declarations at the start of the scope +
      • +
      • make sure a variable is declared only once +
      • +
      • discard unused function arguments +
      • +
      • discard unused inner (named) functions +
      • +
      • finally, try to merge assignments into that one var declaration, if + possible. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.4.1 API

    +
    + + +

    +To use the library from JavaScript, you'd do the following (example for +NodeJS): +

    + + + +
    var jsp = require("uglify-js").parser;
    +var pro = require("uglify-js").uglify;
    +
    +var orig_code = "... JS code here";
    +var ast = jsp.parse(orig_code); // parse code and get the initial AST
    +ast = pro.ast_mangle(ast); // get a new AST with mangled names
    +ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    +var final_code = pro.gen_code(ast); // compressed code here
    +
    + + +

    +The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

    +

    +Some of these functions take optional arguments. Here's a description: +

    +
      +
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. + strict_semicolons is optional and defaults to false. If you pass + true then the parser will throw an error when it expects a semicolon and + it doesn't find it. For most JS code you don't want that, but it's useful + if you want to strictly sanitize your code. + +
    • +
    • pro.ast_lift_variables(ast) – merge and move var declarations to the + scop of the scope; discard unused function arguments or variables; discard + unused (named) inner functions. It also tries to merge assignments + following the var declaration into it. + +

      + If your code is very hand-optimized concerning var declarations, this + lifting variable declarations might actually increase size. For me it + helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also + note that (since it's not enabled by default) this operation isn't yet + heavily tested (please report if you find issues!). +

      +

      + Note that although it might increase the image size (on jQuery it gains + 865 bytes, 243 after gzip) it's technically more correct: in certain + situations, dead code removal might drop variable declarations, which + would not happen if the variables are lifted in advance. +

      +

      + Here's an example of what it does: +

    • +
    + + + + + +
    function f(a, b, c, d, e) {
    +    var q;
    +    var w;
    +    w = 10;
    +    q = 20;
    +    for (var i = 1; i < 10; ++i) {
    +        var boo = foo(a);
    +    }
    +    for (var i = 0; i < 1; ++i) {
    +        var boo = bar(c);
    +    }
    +    function foo(){ ... }
    +    function bar(){ ... }
    +    function baz(){ ... }
    +}
    +
    +// transforms into ==>
    +
    +function f(a, b, c) {
    +    var i, boo, w = 10, q = 20;
    +    for (i = 1; i < 10; ++i) {
    +        boo = foo(a);
    +    }
    +    for (i = 0; i < 1; ++i) {
    +        boo = bar(c);
    +    }
    +    function foo() { ... }
    +    function bar() { ... }
    +}
    +
    + + +
      +
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled + (compressed) variable and function names. It supports the following + options: + +
        +
      • toplevel – mangle toplevel names (by default we don't touch them). +
      • +
      • except – an array of names to exclude from compression. +
      • +
      • defines – an object with properties named after symbols to + replace (see the --define option for the script) and the values + representing the AST replacement value. + +
      • +
      + +
    • +
    • pro.ast_squeeze(ast, options) – employs further optimizations designed + to reduce the size of the code that gen_code would generate from the + AST. Returns a new AST. options can be a hash; the supported options + are: + +
        +
      • make_seqs (default true) which will cause consecutive statements in a + block to be merged using the "sequence" (comma) operator + +
      • +
      • dead_code (default true) which will remove unreachable code. + +
      • +
      + +
    • +
    • pro.gen_code(ast, options) – generates JS code from the AST. By + default it's minified, but using the options argument you can get nicely + formatted output. options is, well, optional :-) and if you pass it it + must be an object and supports the following properties (below you can see + the default values): + +
        +
      • beautify: false – pass true if you want indented output +
      • +
      • indent_start: 0 (only applies when beautify is true) – initial + indentation in spaces +
      • +
      • indent_level: 4 (only applies when beautify is true) -- + indentation level, in spaces (pass an even number) +
      • +
      • quote_keys: false – if you pass true it will quote all keys in + literal objects +
      • +
      • space_colon: false (only applies when beautify is true) – wether + to put a space before the colon in object literals +
      • +
      • ascii_only: false – pass true if you want to encode non-ASCII + characters as \uXXXX. +
      • +
      • inline_script: false – pass true to escape occurrences of + </script in strings +
      • +
      + +
    • +
    + + +
    + +
    + +
    +

    1.4.2 Beautifier shortcoming – no more comments

    +
    + + +

    +The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

    +

    +In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

    +
    + +
    + +
    +

    1.4.3 Use as a code pre-processor

    +
    + + +

    +The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

    +

    +The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

    + + + +
    CLAUSE1: if (typeof DEVMODE === 'undefined') {
    +    DEVMODE = true;
    +}
    +
    +CLAUSE2: function init() {
    +    if (DEVMODE) {
    +        console.log("init() called");
    +    }
    +    ....
    +    DEVMODE &amp;&amp; console.log("init() complete");
    +}
    +
    +CLAUSE3: function reportDeviceStatus(device) {
    +    var DEVMODE = device.mode, DEVNAME = device.name;
    +    if (DEVMODE === 'open') {
    +        ....
    +    }
    +}
    +
    + + +

    +When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

    +

    +If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

    +

    +And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

    +

    +In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

    +

    +It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

    +
    +
    + +
    + +
    +

    1.5 Compression – how good is it?

    +
    + + +

    +Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

    +

    +We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

    + + ++ + + + + + + + + + +
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    + + +
    + +
    + +
    +

    1.6 Bugs?

    +
    + + +

    +Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

    +

    +DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

    +

    +Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

    +
    + +
    + +
    +

    1.7 Links

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

    1.8 License

    +
    + + +

    +UglifyJS is released under the BSD license: +

    + + + +
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    +Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions
    +are met:
    +
    +    * Redistributions of source code must retain the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials
    +      provided with the distribution.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +SUCH DAMAGE.
    +
    + + +
    +

    Footnotes:

    +
    +

    1 I even reported a few bugs and suggested some fixes in the original + parse-js library, and Marijn pushed fixes literally in minutes. +

    +
    +
    + +
    +
    +
    + +
    +

    Date: 2011-12-09 14:59:08 EET

    +

    Author: Mihai Bazon

    +

    Org version 7.7 with Emacs version 23

    +Validate XHTML 1.0 + +
    + + diff --git a/enyo/tools/minifier/node_modules/uglify-js/README.org b/enyo/tools/minifier/node_modules/uglify-js/README.org new file mode 100644 index 0000000..d36b6b2 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/README.org @@ -0,0 +1,578 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =-c= or =----consolidate-primitive-values= --- consolidates null, Boolean, + and String values. Known as aliasing in the Closure Compiler. Worsens the + data compression ratio of gzip. + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    1.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.1.2 obj.toString() ==> obj+“”

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    1.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    1.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    1.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    1.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    1.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    1.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    1.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2011-12-09 14:59:08 EET

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", + "_id": "uglify-js@1.3.2", + "dist": { + "shasum": "0f36c685d58468a2a35945eaaa5f32a3fda555d8" + }, + "_from": "uglify-js@1.3.2" +} diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js b/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js new file mode 100644 index 0000000..f19369e --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js @@ -0,0 +1,28 @@ +#! /usr/bin/env node + +global.sys = require("sys"); +var fs = require("fs"); + +var jsp = require("../lib/parse-js"); +var pro = require("../lib/process"); + +var filename = process.argv[2]; +fs.readFile(filename, "utf8", function(err, text){ + try { + var ast = time_it("parse", function(){ return jsp.parse(text); }); + ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); + ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); + var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); + sys.puts(gen); + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + } +}); + +function time_it(name, cont) { + var t1 = new Date().getTime(); + try { return cont(); } + finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } +}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js b/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js new file mode 100644 index 0000000..14a8002 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js @@ -0,0 +1,409 @@ +#! /usr/bin/env node +global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + +var parseJS = require("../lib/parse-js"); +var sys = require("sys"); + +// write debug in a very straightforward manner +var debug = function(){ + sys.log(Array.prototype.slice.call(arguments).join(', ')); +}; + +var testsPassed = true; + +ParserTestSuite(function(i, input, desc){ + try { + parseJS.parse(input); + debug("ok " + i + ": " + desc); + } catch(e){ + debug("FAIL " + i + " " + desc + " (" + e + ")"); + testsPassed = false; + } +}); + +process.exit(testsPassed ? 0 : 1); + +function ParserTestSuite(callback){ + var inps = [ + ["var abc;", "Regular variable statement w/o assignment"], + ["var abc = 5;", "Regular variable statement with assignment"], + ["/* */;", "Multiline comment"], + ['/** **/;', 'Double star multiline comment'], + ["var f = function(){;};", "Function expression in var assignment"], + ['hi; // moo\n;', 'single line comment'], + ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) + ['a + b;', 'addition'], + ["'a';", 'single string literal'], + ["'a\\n';", 'single string literal with escaped return'], + ['"a";', 'double string literal'], + ['"a\\n";', 'double string literal with escaped return'], + ['"var";', 'string is a keyword'], + ['"variable";', 'string starts with a keyword'], + ['"somevariable";', 'string contains a keyword'], + ['"somevar";', 'string ends with a keyword'], + ['500;', 'int literal'], + ['500.;', 'float literal w/o decimals'], + ['500.432;', 'float literal with decimals'], + ['.432432;', 'float literal w/o int'], + ['(a,b,c);', 'parens and comma'], + ['[1,2,abc];', 'array literal'], + ['var o = {a:1};', 'object literal unquoted key'], + ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... + ['var o = {c:c};', 'object literal keyname is identifier'], + ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], + ['var x;\nvar y;', 'two lines'], + ['var x;\nfunction n(){; }', 'function def'], + ['var x;\nfunction n(abc){; }', 'function def with arg'], + ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], + ['function n(){ "hello"; }', 'function def with body'], + ['/a/;', 'regex literal'], + ['/a/b;', 'regex literal with flag'], + ['/a/ / /b/;', 'regex div regex'], + ['a/b/c;', 'triple division looks like regex'], + ['+function(){/regex/;};', 'regex at start of function body'], + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 + + // first tests for the lexer, should also parse as program (when you append a semi) + + // comments + ['//foo!@#^&$1234\nbar;', 'single line comment'], + ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], + ['/*foo\nbar*/;','multi line comment'], + ['/*x*x*/;','multi line comment with *'], + ['/**/;','empty comment'], + // identifiers + ["x;",'1 identifier'], + ["_x;",'2 identifier'], + ["xyz;",'3 identifier'], + ["$x;",'4 identifier'], + ["x$;",'5 identifier'], + ["_;",'6 identifier'], + ["x5;",'7 identifier'], + ["x_y;",'8 identifier'], + ["x+5;",'9 identifier'], + ["xyz123;",'10 identifier'], + ["x1y1z1;",'11 identifier'], + ["foo\\u00D8bar;",'12 identifier unicode escape'], + //["foo�bar;",'13 identifier unicode embedded (might fail)'], + // numbers + ["5;", '1 number'], + ["5.5;", '2 number'], + ["0;", '3 number'], + ["0.0;", '4 number'], + ["0.001;", '5 number'], + ["1.e2;", '6 number'], + ["1.e-2;", '7 number'], + ["1.E2;", '8 number'], + ["1.E-2;", '9 number'], + [".5;", '10 number'], + [".5e3;", '11 number'], + [".5e-3;", '12 number'], + ["0.5e3;", '13 number'], + ["55;", '14 number'], + ["123;", '15 number'], + ["55.55;", '16 number'], + ["55.55e10;", '17 number'], + ["123.456;", '18 number'], + ["1+e;", '20 number'], + ["0x01;", '22 number'], + ["0XCAFE;", '23 number'], + ["0x12345678;", '24 number'], + ["0x1234ABCD;", '25 number'], + ["0x0001;", '26 number'], + // strings + ["\"foo\";", '1 string'], + ["\'foo\';", '2 string'], + ["\"x\";", '3 string'], + ["\'\';", '4 string'], + ["\"foo\\tbar\";", '5 string'], + ["\"!@#$%^&*()_+{}[]\";", '6 string'], + ["\"/*test*/\";", '7 string'], + ["\"//test\";", '8 string'], + ["\"\\\\\";", '9 string'], + ["\"\\u0001\";", '10 string'], + ["\"\\uFEFF\";", '11 string'], + ["\"\\u10002\";", '12 string'], + ["\"\\x55\";", '13 string'], + ["\"\\x55a\";", '14 string'], + ["\"a\\\\nb\";", '15 string'], + ['";"', '16 string: semi in a string'], + ['"a\\\nb";', '17 string: line terminator escape'], + // literals + ["null;", "null"], + ["true;", "true"], + ["false;", "false"], + // regex + ["/a/;", "1 regex"], + ["/abc/;", "2 regex"], + ["/abc[a-z]*def/g;", "3 regex"], + ["/\\b/;", "4 regex"], + ["/[a-zA-Z]/;", "5 regex"], + + // program tests (for as far as they havent been covered above) + + // regexp + ["/foo(.*)/g;", "another regexp"], + // arrays + ["[];", "1 array"], + ["[ ];", "2 array"], + ["[1];", "3 array"], + ["[1,2];", "4 array"], + ["[1,2,,];", "5 array"], + ["[1,2,3];", "6 array"], + ["[1,2,3,,,];", "7 array"], + // objects + ["{};", "1 object"], + ["({x:5});", "2 object"], + ["({x:5,y:6});", "3 object"], + ["({x:5,});", "4 object"], + ["({if:5});", "5 object"], + ["({ get x() {42;} });", "6 object"], + ["({ set y(a) {1;} });", "7 object"], + // member expression + ["o.m;", "1 member expression"], + ["o['m'];", "2 member expression"], + ["o['n']['m'];", "3 member expression"], + ["o.n.m;", "4 member expression"], + ["o.if;", "5 member expression"], + // call and invoke expressions + ["f();", "1 call/invoke expression"], + ["f(x);", "2 call/invoke expression"], + ["f(x,y);", "3 call/invoke expression"], + ["o.m();", "4 call/invoke expression"], + ["o['m'];", "5 call/invoke expression"], + ["o.m(x);", "6 call/invoke expression"], + ["o['m'](x);", "7 call/invoke expression"], + ["o.m(x,y);", "8 call/invoke expression"], + ["o['m'](x,y);", "9 call/invoke expression"], + ["f(x)(y);", "10 call/invoke expression"], + ["f().x;", "11 call/invoke expression"], + + // eval + ["eval('x');", "1 eval"], + ["(eval)('x');", "2 eval"], + ["(1,eval)('x');", "3 eval"], + ["eval(x,y);", "4 eval"], + // new expression + ["new f();", "1 new expression"], + ["new o;", "2 new expression"], + ["new o.m;", "3 new expression"], + ["new o.m(x);", "4 new expression"], + ["new o.m(x,y);", "5 new expression"], + // prefix/postfix + ["++x;", "1 pre/postfix"], + ["x++;", "2 pre/postfix"], + ["--x;", "3 pre/postfix"], + ["x--;", "4 pre/postfix"], + ["x ++;", "5 pre/postfix"], + ["x /* comment */ ++;", "6 pre/postfix"], + ["++ /* comment */ x;", "7 pre/postfix"], + // unary operators + ["delete x;", "1 unary operator"], + ["void x;", "2 unary operator"], + ["+ x;", "3 unary operator"], + ["-x;", "4 unary operator"], + ["~x;", "5 unary operator"], + ["!x;", "6 unary operator"], + // meh + ["new Date++;", "new date ++"], + ["+x++;", " + x ++"], + // expression expressions + ["1 * 2;", "1 expression expressions"], + ["1 / 2;", "2 expression expressions"], + ["1 % 2;", "3 expression expressions"], + ["1 + 2;", "4 expression expressions"], + ["1 - 2;", "5 expression expressions"], + ["1 << 2;", "6 expression expressions"], + ["1 >>> 2;", "7 expression expressions"], + ["1 >> 2;", "8 expression expressions"], + ["1 * 2 + 3;", "9 expression expressions"], + ["(1+2)*3;", "10 expression expressions"], + ["1*(2+3);", "11 expression expressions"], + ["xy;", "13 expression expressions"], + ["x<=y;", "14 expression expressions"], + ["x>=y;", "15 expression expressions"], + ["x instanceof y;", "16 expression expressions"], + ["x in y;", "17 expression expressions"], + ["x&y;", "18 expression expressions"], + ["x^y;", "19 expression expressions"], + ["x|y;", "20 expression expressions"], + ["x+y>>= y;", "1 assignment"], + ["x <<= y;", "2 assignment"], + ["x = y;", "3 assignment"], + ["x += y;", "4 assignment"], + ["x /= y;", "5 assignment"], + // comma + ["x, y;", "comma"], + // block + ["{};", "1 block"], + ["{x;};", "2 block"], + ["{x;y;};", "3 block"], + // vars + ["var x;", "1 var"], + ["var x,y;", "2 var"], + ["var x=1,y=2;", "3 var"], + ["var x,y=2;", "4 var"], + // empty + [";", "1 empty"], + ["\n;", "2 empty"], + // expression statement + ["x;", "1 expression statement"], + ["5;", "2 expression statement"], + ["1+2;", "3 expression statement"], + // if + ["if (c) x; else y;", "1 if statement"], + ["if (c) x;", "2 if statement"], + ["if (c) {} else {};", "3 if statement"], + ["if (c1) if (c2) s1; else s2;", "4 if statement"], + // while + ["do s; while (e);", "1 while statement"], + ["do { s; } while (e);", "2 while statement"], + ["while (e) s;", "3 while statement"], + ["while (e) { s; };", "4 while statement"], + // for + ["for (;;) ;", "1 for statement"], + ["for (;c;x++) x;", "2 for statement"], + ["for (i;i> 1; +var c = 8 >>> 1; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js new file mode 100644 index 0000000..022f7a3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js @@ -0,0 +1,3 @@ +var a = {}; +a["this"] = 1; +a["that"] = 2; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js new file mode 100644 index 0000000..0b76103 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js @@ -0,0 +1,3 @@ +var a = 2e3; +var b = 2e-3; +var c = 2e-5; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js new file mode 100644 index 0000000..031e85b --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js @@ -0,0 +1 @@ +var s, i; s = ''; i = 0; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js new file mode 100644 index 0000000..060f9df --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js @@ -0,0 +1,9 @@ +function bar(a) { + try { + foo(); + } catch(e) { + alert("Exception caught (foo not defined)"); + } + alert(a); // 10 in FF, "[object Error]" in IE +} +bar(10); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js new file mode 100644 index 0000000..4f8b32f --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js @@ -0,0 +1 @@ +x = (y, z) diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js new file mode 100644 index 0000000..967052e --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js @@ -0,0 +1,3 @@ +foo.toString(); +a.toString(16); +b.toString.call(c); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js new file mode 100644 index 0000000..14054d0 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js @@ -0,0 +1,5 @@ +function f() { + if (a) return; + g(); + function g(){} +}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js new file mode 100644 index 0000000..d25ecd6 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js @@ -0,0 +1 @@ +[(a,b)] diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js new file mode 100644 index 0000000..6158861 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js @@ -0,0 +1,4 @@ +var a = { + a: 1, + b: 2, // <-- trailing comma +}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js new file mode 100644 index 0000000..c271a26 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js @@ -0,0 +1,5 @@ +(function() { + var x = function fun(a, fun, b) { + return fun; + }; +}()); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js new file mode 100644 index 0000000..a675b1c --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js @@ -0,0 +1 @@ +var nullString = "\0" \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js new file mode 100644 index 0000000..b631f4c --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js @@ -0,0 +1,3 @@ +typeof a === 'string' +b + "" !== c + "" +d < e === f < g diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js new file mode 100644 index 0000000..746ea98 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js @@ -0,0 +1,3 @@ +// var declarations after each other should be combined +var a = 1; +var b = 2; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js new file mode 100644 index 0000000..6a15c46 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js @@ -0,0 +1,21 @@ +function id(a) { + // Form-Feed + // Vertical Tab + // No-Break Space + ᠎// Mongolian Vowel Separator +  // En quad +  // Em quad +  // En space +  // Em space +  // Three-Per-Em Space +  // Four-Per-Em Space +  // Six-Per-Em Space +  // Figure Space +  // Punctuation Space +  // Thin Space +  // Hair Space +  // Narrow No-Break Space +  // Medium Mathematical Space +  // Ideographic Space + return a; +} diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js new file mode 100644 index 0000000..de266ed --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js @@ -0,0 +1,2 @@ +with({}) { +}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js new file mode 100644 index 0000000..564abd3 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js @@ -0,0 +1,57 @@ +global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + +var fs = require('fs'), + uglify = require('../../uglify-js'), + jsp = uglify.parser, + nodeunit = require('nodeunit'), + path = require('path'), + pro = uglify.uglify; + +var Script = process.binding('evals').Script; + +var scriptsPath = __dirname; + +function compress(code) { + var ast = jsp.parse(code); + ast = pro.ast_mangle(ast, { mangle: true }); + ast = pro.ast_squeeze(ast, { no_warnings: true }); + ast = pro.ast_squeeze_more(ast); + return pro.gen_code(ast); +}; + +var testDir = path.join(scriptsPath, "compress", "test"); +var expectedDir = path.join(scriptsPath, "compress", "expected"); + +function getTester(script) { + return function(test) { + var testPath = path.join(testDir, script); + var expectedPath = path.join(expectedDir, script); + var content = fs.readFileSync(testPath, 'utf-8'); + var outputCompress = compress(content); + + // Check if the noncompressdata is larger or same size as the compressed data + test.ok(content.length >= outputCompress.length); + + // Check that a recompress gives the same result + var outputReCompress = compress(content); + test.equal(outputCompress, outputReCompress); + + // Check if the compressed output is what is expected + var expected = fs.readFileSync(expectedPath, 'utf-8'); + test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); + + test.done(); + }; +}; + +var tests = {}; + +var scripts = fs.readdirSync(testDir); +for (var i in scripts) { + var script = scripts[i]; + if (/\.js$/.test(script)) { + tests[script] = getTester(script); + } +} + +module.exports = nodeunit.testCase(tests); diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js new file mode 100644 index 0000000..4bf2b94 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js new file mode 100644 index 0000000..c6a9d79 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js new file mode 100644 index 0000000..f295fba --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); diff --git a/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js b/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js new file mode 100644 index 0000000..6e14a63 --- /dev/null +++ b/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js @@ -0,0 +1,18 @@ +//convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); +uglify.consolidator = require("./lib/consolidator"); + +module.exports = uglify diff --git a/enyo/tools/minifier/node_modules/walker.js b/enyo/tools/minifier/node_modules/walker.js new file mode 100644 index 0000000..11c4355 --- /dev/null +++ b/enyo/tools/minifier/node_modules/walker.js @@ -0,0 +1,40 @@ +var fs = require("fs"); + +// +// setup DOM-like sandbox +// + +var window = {}; +var loader; + +var script = function(inPath) { + eval(fs.readFileSync(inPath, "utf8")); +}; + +module.exports = { + init: function(inEnyoPath) { + script(inEnyoPath + "/loader.js"); + enyo.path.addPaths({ + enyo: inEnyoPath, + lib: inEnyoPath + "/../lib" + }); + loader = new enyo.loaderFactory({ + script: function() {}, + sheet: function() {} + }); + loader.loadPackage = function(inScript) { + script(inScript); + }; + enyo.depends = function() { + //console.log(arguments); + loader.load.apply(loader, arguments); + }; + }, + walk: function(inScript, inCallback) { + //console.log("walking: ", inScript); + loader.finish = function() { + inCallback(loader); + }; + script(enyo.path.rewrite(inScript)); + } +} \ No newline at end of file diff --git a/enyo/tools/minifier/path-relative-shim.js b/enyo/tools/minifier/path-relative-shim.js new file mode 100644 index 0000000..ea5d9b2 --- /dev/null +++ b/enyo/tools/minifier/path-relative-shim.js @@ -0,0 +1,135 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +/* + + path.relative shim for older versions of node + +*/ + +var isWindows = process.platform === 'win32'; +var path = require('path'); + +if (isWindows) { + + // path.relative(from, to) + // it will solve the relative path from 'from' to 'to', for instance: + // from = 'C:\\orandea\\test\\aaa' + // to = 'C:\\orandea\\impl\\bbb' + // The output of the function should be: '..\\..\\impl\\bbb' + // windows version + exports.relative = function(from, to) { + from = path.resolve(from); + to = path.resolve(to); + + // windows is not case sensitive + var lowerFrom = from.toLowerCase(); + var lowerTo = to.toLowerCase(); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var toParts = trim(to.split('\\')); + + var lowerFromParts = trim(lowerFrom.split('\\')); + var lowerToParts = trim(lowerTo.split('\\')); + + var length = Math.min(lowerFromParts.length, lowerToParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (lowerFromParts[i] !== lowerToParts[i]) { + samePartsLength = i; + break; + } + } + + if (samePartsLength == 0) { + return to; + } + + var outputParts = []; + for (var i = samePartsLength; i < lowerFromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('\\'); + }; + +} else /* posix */ { + + // path.relative(from, to) + // posix version + exports.relative = function(from, to) { + from = path.resolve(from).substr(1); + to = path.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); + }; + +} \ No newline at end of file diff --git a/enyo/tools/minify.bat b/enyo/tools/minify.bat new file mode 100644 index 0000000..a058a37 --- /dev/null +++ b/enyo/tools/minify.bat @@ -0,0 +1,17 @@ +REM don't watch the sausage being made +@ECHO OFF + +REM the folder this script is in (*/enyo/tools) +SET TOOLS=%~DP0 + +REM enyo location +SET ENYO=%TOOLS%\.. + +REM minify script location +SET MINIFY=%TOOLS%\minifier\minify.js + +REM node location +SET NODE=node.exe + +REM use node to invoke minify with a known path to enyo and imported parameters +%NODE% "%MINIFY%" -enyo "%ENYO%" %* diff --git a/enyo/tools/minify.sh b/enyo/tools/minify.sh new file mode 100644 index 0000000..80fedcc --- /dev/null +++ b/enyo/tools/minify.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# the folder this script is in (*/enyo/tools) +TOOLS="$(cd `dirname $0`; pwd)" +# enyo location +ENYO="$TOOLS/.." +# minify script location +MINIFY="$TOOLS/minifier/minify.js" + +# check for node, but quietly +if command -v node >/dev/null 2>&1; then + # use node to invoke minify with a known path to enyo and imported parameters + echo "enyo/tools/minify.sh args: " $@ + node "$MINIFY" -enyo "$ENYO" $@ +else + echo "No node found in path" + exit 1 +fi diff --git a/enyo/tools/node_modules/.bin/nopt b/enyo/tools/node_modules/.bin/nopt new file mode 100644 index 0000000..df90c72 --- /dev/null +++ b/enyo/tools/node_modules/.bin/nopt @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/enyo/tools/node_modules/.bin/shjs b/enyo/tools/node_modules/.bin/shjs new file mode 100644 index 0000000..faa9995 --- /dev/null +++ b/enyo/tools/node_modules/.bin/shjs @@ -0,0 +1,43 @@ +#!/usr/bin/env node +require('../global'); + +if (process.argv.length < 3) { + console.log('ShellJS: missing argument (script name)'); + console.log(); + process.exit(1); +} + +var scriptName = process.argv[2]; +env['NODE_PATH'] = __dirname + '/../..'; + +if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { + if (test('-f', scriptName + '.js')) + scriptName += '.js'; + if (test('-f', scriptName + '.coffee')) + scriptName += '.coffee'; +} + +if (!test('-f', scriptName)) { + console.log('ShellJS: script not found ('+scriptName+')'); + console.log(); + process.exit(1); +} + + +if (scriptName.match(/\.coffee$/)) { + // + // CoffeeScript + // + if (which('coffee')) { + exec('coffee ' + scriptName, { async: true }); + } else { + console.log('ShellJS: CoffeeScript interpreter not found'); + console.log(); + process.exit(1); + } +} else { + // + // JavaScript + // + exec('node ' + scriptName, { async: true }); +} diff --git a/enyo/tools/node_modules/nopt/.npmignore b/enyo/tools/node_modules/nopt/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/enyo/tools/node_modules/nopt/LICENSE b/enyo/tools/node_modules/nopt/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/enyo/tools/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/enyo/tools/node_modules/nopt/README.md b/enyo/tools/node_modules/nopt/README.md new file mode 100644 index 0000000..f290da8 --- /dev/null +++ b/enyo/tools/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/enyo/tools/node_modules/nopt/bin/nopt.js b/enyo/tools/node_modules/nopt/bin/nopt.js new file mode 100644 index 0000000..df90c72 --- /dev/null +++ b/enyo/tools/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/enyo/tools/node_modules/nopt/examples/my-program.js b/enyo/tools/node_modules/nopt/examples/my-program.js new file mode 100644 index 0000000..142447e --- /dev/null +++ b/enyo/tools/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/enyo/tools/node_modules/nopt/lib/nopt.js b/enyo/tools/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..5763860 --- /dev/null +++ b/enyo/tools/node_modules/nopt/lib/nopt.js @@ -0,0 +1,555 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md b/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js new file mode 100644 index 0000000..037de2d --- /dev/null +++ b/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,106 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Array.prototype.abbrev = function () { return abbrev(this) } + Object.prototype.abbrev = function () { return abbrev(Object.keys(this)) } +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (nextMatches || prevMatches) continue + else { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") + , sys +sys = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+sys.inspect(list)+") === " + sys.inspect(expect) + "\n"+ + "actual: "+sys.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + sys.inspect(expect) + "\n"+ + "actual: "+sys.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json b/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json new file mode 100644 index 0000000..09b485e --- /dev/null +++ b/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,20 @@ +{ + "name": "abbrev", + "version": "1.0.3", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "_id": "abbrev@1.0.3", + "_from": "abbrev@1" +} diff --git a/enyo/tools/node_modules/nopt/package.json b/enyo/tools/node_modules/nopt/package.json new file mode 100644 index 0000000..77a120d --- /dev/null +++ b/enyo/tools/node_modules/nopt/package.json @@ -0,0 +1,31 @@ +{ + "name": "nopt", + "version": "2.0.0", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", + "_id": "nopt@2.0.0", + "_from": "nopt" +} diff --git a/enyo/tools/node_modules/shelljs/.documentup.json b/enyo/tools/node_modules/shelljs/.documentup.json new file mode 100644 index 0000000..2d0c727 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/.documentup.json @@ -0,0 +1,6 @@ +{ + "name": "ShellJS", + "twitter": [ + "arturadib" + ] +} diff --git a/enyo/tools/node_modules/shelljs/.travis.yml b/enyo/tools/node_modules/shelljs/.travis.yml new file mode 100644 index 0000000..70076dc --- /dev/null +++ b/enyo/tools/node_modules/shelljs/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - 0.4 + - 0.6 + - 0.7 # development version of 0.8, may be unstable + diff --git a/enyo/tools/node_modules/shelljs/LICENSE b/enyo/tools/node_modules/shelljs/LICENSE new file mode 100644 index 0000000..1b35ee9 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2012, Artur Adib +All rights reserved. + +You may use this project under the terms of the New BSD license as follows: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Artur Adib nor the + names of the contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/enyo/tools/node_modules/shelljs/README.md b/enyo/tools/node_modules/shelljs/README.md new file mode 100644 index 0000000..ddf5f5d --- /dev/null +++ b/enyo/tools/node_modules/shelljs/README.md @@ -0,0 +1,421 @@ +# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs) + +ShellJS is a portable (**Windows included**) implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts! + +The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and is being used at Mozilla's [PDF.js](http://github.com/mozilla/pdf.js), [Butter.js](http://github.com/mozilla/butter) and [others](http://search.npmjs.org/#/shelljs). + + +## Installing + +Via npm: + +```bash +$ npm install [-g] shelljs +``` + +If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to +run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder: + +```bash +$ shjs my_script +``` + +You can also just copy `shell.js` into your project's directory, and `require()` accordingly. + + +## Examples + +### JavaScript + +```javascript +require('shelljs/global'); + +if (!which('git')) { + echo('Sorry, this script requires git'); + exit(1); +} + +// Copy files to release dir +mkdir('-p', 'out/Release'); +cp('-R', 'stuff/*', 'out/Release'); + +// Replace macros in each .js file +cd('lib'); +ls('*.js').forEach(function(file) { + sed('-i', 'BUILD_VERSION', 'v0.1.2', file); + sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file); + sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file); +}); +cd('..'); + +// Run external tool synchronously +if (exec('git commit -am "Auto-commit"').code !== 0) { + echo('Error: Git commit failed'); + exit(1); +} +``` + +### CoffeeScript + +```coffeescript +require 'shelljs/global' + +if not which 'git' + echo 'Sorry, this script requires git' + exit 1 + +# Copy files to release dir +mkdir '-p', 'out/Release' +cp '-R', 'stuff/*', 'out/Release' + +# Replace macros in each .js file +cd 'lib' +for file in ls '*.js' + sed '-i', 'BUILD_VERSION', 'v0.1.2', file + sed '-i', /.*REMOVE_THIS_LINE.*\n/, '', file + sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat 'macro.js', file +cd '..' + +# Run external tool synchronously +if (exec 'git commit -am "Auto-commit"').code != 0 + echo 'Error: Git commit failed' + exit 1 +``` + +## Global vs. Local + +The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`. + +Example: + +```javascript +var shell = require('shelljs'); +shell.echo('hello world'); +``` + +## Make tool + +A convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script. + +Example (CoffeeScript): + +```coffeescript +require 'shelljs/make' + +target.all = -> + target.bundle() + target.docs() + +target.bundle = -> + cd __dirname + mkdir 'build' + cd 'lib' + (cat '*.js').to '../build/output.js' + +target.docs = -> + cd __dirname + mkdir 'docs' + cd 'lib' + for file in ls '*.js' + text = grep '//@', file # extract special comments + text.replace '//@', '' # remove comment tags + text.to 'docs/my_docs.md' +``` + +To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on. + + + + + + +## Command reference + + +All commands run synchronously, unless otherwise stated. + + +### cd('dir') +Changes to directory `dir` for the duration of the script + +### pwd() +Returns the current directory. + +### ls([options ,] path [,path ...]) +### ls([options ,] path_array) +Available options: + ++ `-R`: recursive ++ `-A`: all files (include files beginning with `.`, except for `.` and `..`) + +Examples: + +```javascript +ls('projs/*.js'); +ls('-R', '/users/me', '/tmp'); +ls('-R', ['/users/me', '/tmp']); // same as above +``` + +Returns array of files in the given path, or in current directory if no path provided. + +### find(path [,path ...]) +### find(path_array) +Examples: + +```javascript +find('src', 'lib'); +find(['src', 'lib']); // same as above +find('.').filter(function(file) { return file.match(/\.js$/); }); +``` + +Returns array of all files (however deep) in the given paths. + +The main difference from `ls('-R', path)` is that the resulting file names +include the base directories, e.g. `lib/resources/file1` instead of just `file1`. + +### cp([options ,] source [,source ...], dest) +### cp([options ,] source_array, dest) +Available options: + ++ `-f`: force ++ `-r, -R`: recursive + +Examples: + +```javascript +cp('file1', 'dir1'); +cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); +cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above +``` + +Copies files. The wildcard `*` is accepted. + +### rm([options ,] file [, file ...]) +### rm([options ,] file_array) +Available options: + ++ `-f`: force ++ `-r, -R`: recursive + +Examples: + +```javascript +rm('-rf', '/tmp/*'); +rm('some_file.txt', 'another_file.txt'); +rm(['some_file.txt', 'another_file.txt']); // same as above +``` + +Removes files. The wildcard `*` is accepted. + +### mv(source [, source ...], dest') +### mv(source_array, dest') +Available options: + ++ `f`: force + +Examples: + +```javascript +mv('-f', 'file', 'dir/'); +mv('file1', 'file2', 'dir/'); +mv(['file1', 'file2'], 'dir/'); // same as above +``` + +Moves files. The wildcard `*` is accepted. + +### mkdir([options ,] dir [, dir ...]) +### mkdir([options ,] dir_array) +Available options: + ++ `p`: full path (will create intermediate dirs if necessary) + +Examples: + +```javascript +mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); +mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above +``` + +Creates directories. + +### test(expression) +Available expression primaries: + ++ `'-b', 'path'`: true if path is a block device ++ `'-c', 'path'`: true if path is a character device ++ `'-d', 'path'`: true if path is a directory ++ `'-e', 'path'`: true if path exists ++ `'-f', 'path'`: true if path is a regular file ++ `'-L', 'path'`: true if path is a symboilc link ++ `'-p', 'path'`: true if path is a pipe (FIFO) ++ `'-S', 'path'`: true if path is a socket + +Examples: + +```javascript +if (test('-d', path)) { /* do something with dir */ }; +if (!test('-f', path)) continue; // skip if it's a regular file +``` + +Evaluates expression using the available primaries and returns corresponding value. + +### cat(file [, file ...]) +### cat(file_array) + +Examples: + +```javascript +var str = cat('file*.txt'); +var str = cat('file1', 'file2'); +var str = cat(['file1', 'file2']); // same as above +``` + +Returns a string containing the given file, or a concatenated string +containing the files if more than one file is given (a new line character is +introduced between each file). Wildcard `*` accepted. + +### 'string'.to(file) + +Examples: + +```javascript +cat('input.txt').to('output.txt'); +``` + +Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as +those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ + +### sed([options ,] search_regex, replace_str, file) +Available options: + ++ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ + +Examples: + +```javascript +sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); +sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); +``` + +Reads an input string from `file` and performs a JavaScript `replace()` on the input +using the given search regex and replacement string. Returns the new string after replacement. + +### grep([options ,] regex_filter, file [, file ...]) +### grep([options ,] regex_filter, file_array) +Available options: + ++ `-v`: Inverse the sense of the regex and print the lines not matching the criteria. + +Examples: + +```javascript +grep('-v', 'GLOBAL_VARIABLE', '*.js'); +grep('GLOBAL_VARIABLE', '*.js'); +``` + +Reads input string from given files and returns a string containing all lines of the +file that match the given `regex_filter`. Wildcard `*` accepted. + +### which(command) + +Examples: + +```javascript +var nodeExec = which('node'); +``` + +Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. +Returns string containing the absolute path to the command. + +### echo(string [,string ...]) + +Examples: + +```javascript +echo('hello world'); +var str = echo('hello world'); +``` + +Prints string to stdout, and returns string with additional utility methods +like `.to()`. + +### exit(code) +Exits the current process with the given exit code. + +### env['VAR_NAME'] +Object containing environment variables (both getter and setter). Shortcut to process.env. + +### exec(command [, options] [, callback]) +Available options (all `false` by default): + ++ `async`: Asynchronous execution. Defaults to true if a callback is provided. ++ `silent`: Do not echo program output to console. + +Examples: + +```javascript +var version = exec('node --version', {silent:true}).output; + +var child = exec('some_long_running_process', {async:true}); +child.stdout.on('data', function(data) { + /* ... do something with data ... */ +}); + +exec('some_long_running_process', function(code, output) { + console.log('Exit code:', code); + console.log('Program output:', output); +}); +``` + +Executes the given `command` _synchronously_, unless otherwise specified. +When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's +`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and +the `callback` gets the arguments `(code, output)`. + +**Note:** For long-lived processes, it's best to run `exec()` asynchronously as +the current synchronous implementation uses a lot of CPU. This should be getting +fixed soon. + +## Non-Unix commands + + +### tempdir() +Searches and returns string containing a writeable, platform-dependent temporary directory. +Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). + +### error() +Tests if error occurred in the last command. Returns `null` if no error occurred, +otherwise returns string explaining the error + +### silent([state]) +Example: + +```javascript +var silentState = silent(); +silent(true); +/* ... */ +silent(silentState); // restore old silent state +``` + +Suppresses all command output if `state = true`, except for `echo()` calls. +Returns state if no arguments given. + +## Deprecated + + +### exists(path [, path ...]) +### exists(path_array) + +_This function is being deprecated. Use `test()` instead._ + +Returns true if all the given paths exist. + +### verbose() + +_This function is being deprecated. Use `silent(false) instead.`_ + +Enables all output (default) diff --git a/enyo/tools/node_modules/shelljs/bin/shjs b/enyo/tools/node_modules/shelljs/bin/shjs new file mode 100644 index 0000000..faa9995 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/bin/shjs @@ -0,0 +1,43 @@ +#!/usr/bin/env node +require('../global'); + +if (process.argv.length < 3) { + console.log('ShellJS: missing argument (script name)'); + console.log(); + process.exit(1); +} + +var scriptName = process.argv[2]; +env['NODE_PATH'] = __dirname + '/../..'; + +if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { + if (test('-f', scriptName + '.js')) + scriptName += '.js'; + if (test('-f', scriptName + '.coffee')) + scriptName += '.coffee'; +} + +if (!test('-f', scriptName)) { + console.log('ShellJS: script not found ('+scriptName+')'); + console.log(); + process.exit(1); +} + + +if (scriptName.match(/\.coffee$/)) { + // + // CoffeeScript + // + if (which('coffee')) { + exec('coffee ' + scriptName, { async: true }); + } else { + console.log('ShellJS: CoffeeScript interpreter not found'); + console.log(); + process.exit(1); + } +} else { + // + // JavaScript + // + exec('node ' + scriptName, { async: true }); +} diff --git a/enyo/tools/node_modules/shelljs/global.js b/enyo/tools/node_modules/shelljs/global.js new file mode 100644 index 0000000..83a27e6 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/global.js @@ -0,0 +1,3 @@ +var shell = require('./shell.js'); +for (cmd in shell) + global[cmd] = shell[cmd]; diff --git a/enyo/tools/node_modules/shelljs/make.js b/enyo/tools/node_modules/shelljs/make.js new file mode 100644 index 0000000..c495735 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/make.js @@ -0,0 +1,46 @@ +require('./global'); + +global.target = {}; + +// This ensures we only execute the script targets after the entire script has +// been evaluated +var args = process.argv.slice(2); +setTimeout(function() { + + if (args.length === 1 && args[0] === '--help') { + console.log('Available targets:'); + for (t in target) + console.log(' ' + t); + return; + } + + // Wrap targets to prevent duplicate execution + for (t in target) { + (function(t, oldTarget){ + + // Wrap it + target[t] = function(force) { + if (oldTarget.done && !force) + return; + oldTarget.done = true; + return oldTarget.apply(oldTarget, arguments); + } + + })(t, target[t]); + } + + // Execute desired targets + if (args.length > 0) { + args.forEach(function(arg) { + if (arg in target) + target[arg](); + else { + console.log('no such target: ' + arg); + exit(1); + } + }); + } else if ('all' in target) { + target.all(); + } + +}, 0); diff --git a/enyo/tools/node_modules/shelljs/package.json b/enyo/tools/node_modules/shelljs/package.json new file mode 100644 index 0000000..a3cfd41 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/package.json @@ -0,0 +1,39 @@ +{ + "name": "shelljs", + "version": "0.0.8", + "author": { + "name": "Artur Adib", + "email": "aadib@mozilla.com" + }, + "description": "Portable Unix shell commands for Node.js", + "keywords": [ + "unix", + "shell", + "makefile", + "make", + "jake", + "synchronous" + ], + "repository": { + "type": "git", + "url": "git://github.com/arturadib/shelljs.git" + }, + "homepage": "http://github.com/arturadib/shelljs", + "main": "./shell.js", + "scripts": { + "test": "node scripts/run-tests" + }, + "bin": { + "shjs": "./bin/shjs" + }, + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs)\n\nShellJS is a portable (**Windows included**) implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts!\n\nThe project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and is being used at Mozilla's [PDF.js](http://github.com/mozilla/pdf.js), [Butter.js](http://github.com/mozilla/butter) and [others](http://search.npmjs.org/#/shelljs).\n\n\n## Installing\n\nVia npm:\n\n```bash\n$ npm install [-g] shelljs\n```\n\nIf the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to\nrun ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:\n\n```bash\n$ shjs my_script\n```\n\nYou can also just copy `shell.js` into your project's directory, and `require()` accordingly.\n\n\n## Examples\n\n### JavaScript\n\n```javascript\nrequire('shelljs/global');\n\nif (!which('git')) {\n echo('Sorry, this script requires git');\n exit(1);\n}\n\n// Copy files to release dir\nmkdir('-p', 'out/Release');\ncp('-R', 'stuff/*', 'out/Release');\n\n// Replace macros in each .js file\ncd('lib');\nls('*.js').forEach(function(file) {\n sed('-i', 'BUILD_VERSION', 'v0.1.2', file);\n sed('-i', /.*REMOVE_THIS_LINE.*\\n/, '', file);\n sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat('macro.js'), file);\n});\ncd('..');\n\n// Run external tool synchronously\nif (exec('git commit -am \"Auto-commit\"').code !== 0) {\n echo('Error: Git commit failed');\n exit(1);\n}\n```\n\n### CoffeeScript\n\n```coffeescript\nrequire 'shelljs/global'\n\nif not which 'git'\n echo 'Sorry, this script requires git'\n exit 1\n\n# Copy files to release dir\nmkdir '-p', 'out/Release'\ncp '-R', 'stuff/*', 'out/Release'\n\n# Replace macros in each .js file\ncd 'lib'\nfor file in ls '*.js'\n sed '-i', 'BUILD_VERSION', 'v0.1.2', file\n sed '-i', /.*REMOVE_THIS_LINE.*\\n/, '', file\n sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat 'macro.js', file\ncd '..'\n\n# Run external tool synchronously\nif (exec 'git commit -am \"Auto-commit\"').code != 0\n echo 'Error: Git commit failed'\n exit 1\n```\n\n## Global vs. Local\n\nThe example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.\n\nExample:\n\n```javascript\nvar shell = require('shelljs');\nshell.echo('hello world');\n```\n\n## Make tool\n\nA convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script.\n\nExample (CoffeeScript):\n\n```coffeescript\nrequire 'shelljs/make'\n\ntarget.all = ->\n target.bundle()\n target.docs()\n\ntarget.bundle = ->\n cd __dirname\n mkdir 'build'\n cd 'lib'\n (cat '*.js').to '../build/output.js'\n\ntarget.docs = ->\n cd __dirname\n mkdir 'docs'\n cd 'lib'\n for file in ls '*.js'\n text = grep '//@', file # extract special comments\n text.replace '//@', '' # remove comment tags\n text.to 'docs/my_docs.md'\n```\n\nTo run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.\n\n\n\n\n\n\n## Command reference\n\n\nAll commands run synchronously, unless otherwise stated.\n\n\n### cd('dir')\nChanges to directory `dir` for the duration of the script\n\n### pwd()\nReturns the current directory.\n\n### ls([options ,] path [,path ...])\n### ls([options ,] path_array)\nAvailable options:\n\n+ `-R`: recursive\n+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)\n\nExamples:\n\n```javascript\nls('projs/*.js');\nls('-R', '/users/me', '/tmp');\nls('-R', ['/users/me', '/tmp']); // same as above\n```\n\nReturns array of files in the given path, or in current directory if no path provided.\n\n### find(path [,path ...])\n### find(path_array)\nExamples:\n\n```javascript\nfind('src', 'lib');\nfind(['src', 'lib']); // same as above\nfind('.').filter(function(file) { return file.match(/\\.js$/); });\n```\n\nReturns array of all files (however deep) in the given paths.\n\nThe main difference from `ls('-R', path)` is that the resulting file names \ninclude the base directories, e.g. `lib/resources/file1` instead of just `file1`.\n\n### cp([options ,] source [,source ...], dest)\n### cp([options ,] source_array, dest)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\ncp('file1', 'dir1');\ncp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');\ncp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above\n```\n\nCopies files. The wildcard `*` is accepted.\n\n### rm([options ,] file [, file ...])\n### rm([options ,] file_array)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\nrm('-rf', '/tmp/*');\nrm('some_file.txt', 'another_file.txt');\nrm(['some_file.txt', 'another_file.txt']); // same as above\n```\n\nRemoves files. The wildcard `*` is accepted. \n\n### mv(source [, source ...], dest')\n### mv(source_array, dest')\nAvailable options:\n\n+ `f`: force\n\nExamples:\n\n```javascript\nmv('-f', 'file', 'dir/');\nmv('file1', 'file2', 'dir/');\nmv(['file1', 'file2'], 'dir/'); // same as above\n```\n\nMoves files. The wildcard `*` is accepted.\n\n### mkdir([options ,] dir [, dir ...])\n### mkdir([options ,] dir_array)\nAvailable options:\n\n+ `p`: full path (will create intermediate dirs if necessary)\n\nExamples:\n\n```javascript\nmkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');\nmkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above\n```\n\nCreates directories.\n\n### test(expression)\nAvailable expression primaries:\n\n+ `'-b', 'path'`: true if path is a block device\n+ `'-c', 'path'`: true if path is a character device\n+ `'-d', 'path'`: true if path is a directory\n+ `'-e', 'path'`: true if path exists\n+ `'-f', 'path'`: true if path is a regular file\n+ `'-L', 'path'`: true if path is a symboilc link\n+ `'-p', 'path'`: true if path is a pipe (FIFO)\n+ `'-S', 'path'`: true if path is a socket\n\nExamples:\n\n```javascript\nif (test('-d', path)) { /* do something with dir */ };\nif (!test('-f', path)) continue; // skip if it's a regular file\n```\n\nEvaluates expression using the available primaries and returns corresponding value.\n\n### cat(file [, file ...])\n### cat(file_array)\n\nExamples:\n\n```javascript\nvar str = cat('file*.txt');\nvar str = cat('file1', 'file2');\nvar str = cat(['file1', 'file2']); // same as above\n```\n\nReturns a string containing the given file, or a concatenated string\ncontaining the files if more than one file is given (a new line character is\nintroduced between each file). Wildcard `*` accepted.\n\n### 'string'.to(file)\n\nExamples:\n\n```javascript\ncat('input.txt').to('output.txt');\n```\n\nAnalogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as\nthose returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_\n\n### sed([options ,] search_regex, replace_str, file)\nAvailable options:\n\n+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_\n\nExamples:\n\n```javascript\nsed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');\nsed(/.*DELETE_THIS_LINE.*\\n/, '', 'source.js');\n```\n\nReads an input string from `file` and performs a JavaScript `replace()` on the input\nusing the given search regex and replacement string. Returns the new string after replacement.\n\n### grep([options ,] regex_filter, file [, file ...])\n### grep([options ,] regex_filter, file_array)\nAvailable options:\n\n+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria.\n\nExamples:\n\n```javascript\ngrep('-v', 'GLOBAL_VARIABLE', '*.js');\ngrep('GLOBAL_VARIABLE', '*.js');\n```\n\nReads input string from given files and returns a string containing all lines of the \nfile that match the given `regex_filter`. Wildcard `*` accepted.\n\n### which(command)\n\nExamples:\n\n```javascript\nvar nodeExec = which('node');\n```\n\nSearches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.\nReturns string containing the absolute path to the command.\n\n### echo(string [,string ...])\n\nExamples:\n\n```javascript\necho('hello world');\nvar str = echo('hello world');\n```\n\nPrints string to stdout, and returns string with additional utility methods\nlike `.to()`.\n\n### exit(code)\nExits the current process with the given exit code.\n\n### env['VAR_NAME']\nObject containing environment variables (both getter and setter). Shortcut to process.env.\n\n### exec(command [, options] [, callback])\nAvailable options (all `false` by default):\n\n+ `async`: Asynchronous execution. Defaults to true if a callback is provided.\n+ `silent`: Do not echo program output to console.\n\nExamples:\n\n```javascript\nvar version = exec('node --version', {silent:true}).output;\n\nvar child = exec('some_long_running_process', {async:true});\nchild.stdout.on('data', function(data) { \n /* ... do something with data ... */ \n});\n\nexec('some_long_running_process', function(code, output) {\n console.log('Exit code:', code);\n console.log('Program output:', output);\n});\n```\n\nExecutes the given `command` _synchronously_, unless otherwise specified. \nWhen in synchronous mode returns the object `{ code:..., output:... }`, containing the program's \n`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and\nthe `callback` gets the arguments `(code, output)`.\n\n**Note:** For long-lived processes, it's best to run `exec()` asynchronously as\nthe current synchronous implementation uses a lot of CPU. This should be getting\nfixed soon.\n\n## Non-Unix commands\n\n\n### tempdir()\nSearches and returns string containing a writeable, platform-dependent temporary directory.\nFollows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).\n\n### error()\nTests if error occurred in the last command. Returns `null` if no error occurred,\notherwise returns string explaining the error\n\n### silent([state])\nExample:\n\n```javascript\nvar silentState = silent();\nsilent(true);\n/* ... */\nsilent(silentState); // restore old silent state\n```\n\nSuppresses all command output if `state = true`, except for `echo()` calls. \nReturns state if no arguments given.\n\n## Deprecated\n\n\n### exists(path [, path ...])\n### exists(path_array)\n\n_This function is being deprecated. Use `test()` instead._\n\nReturns true if all the given paths exist.\n\n### verbose()\n\n_This function is being deprecated. Use `silent(false) instead.`_\n\nEnables all output (default)\n", + "readmeFilename": "README.md", + "_id": "shelljs@0.0.8", + "_from": "shelljs" +} diff --git a/enyo/tools/node_modules/shelljs/scripts/docs.js b/enyo/tools/node_modules/shelljs/scripts/docs.js new file mode 100644 index 0000000..68a2138 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/scripts/docs.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +require('../global'); + +echo('Appending docs to README.md'); + +cd(__dirname + '/..'); + +// Extract docs from shell.js +var docs = grep('//@', 'shell.js'); +// Remove '//@' +docs = docs.replace(/\/\/\@ ?/g, ''); +// Append docs to README +sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md'); + +echo('All done.'); diff --git a/enyo/tools/node_modules/shelljs/scripts/run-tests.js b/enyo/tools/node_modules/shelljs/scripts/run-tests.js new file mode 100644 index 0000000..1268080 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/scripts/run-tests.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node +require('../global'); + +var failed = false; + +cd(__dirname + '/../test'); +ls('*.js').forEach(function(file) { + echo('Running test:', file); + if (exec('node '+file).code !== 123) { // 123 avoids false positives (e.g. premature exit) + failed = true; + echo('*** FAILED! (missing return code)'); + } +}); + +if (failed) { + echo(); + echo('WARNING: Some tests did not pass!'); + exit(1); +} else { + echo(); + echo('All tests passed.'); +} diff --git a/enyo/tools/node_modules/shelljs/shell.js b/enyo/tools/node_modules/shelljs/shell.js new file mode 100644 index 0000000..7881f67 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/shell.js @@ -0,0 +1,1513 @@ +// +// ShellJS +// Unix shell commands on top of Node's API +// +// Copyright (c) 2012 Artur Adib +// http://github.com/arturadib/shelljs +// + +var fs = require('fs'), + path = require('path'), + util = require('util'), + vm = require('vm'), + child = require('child_process'), + os = require('os'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +var state = { + error: null, + fatal: false, + silent: false, + currentCmd: 'shell.js', + tempDir: null + }, + platform = os.type().match(/^Win/) ? 'win' : 'unix'; + + +//@ +//@ All commands run synchronously, unless otherwise stated. +//@ + + +//@ +//@ ### cd('dir') +//@ Changes to directory `dir` for the duration of the script +function _cd(options, dir) { + if (!dir) + error('directory not specified'); + + if (!fs.existsSync(dir)) + error('no such file or directory: ' + dir); + + if (fs.existsSync(dir) && !fs.statSync(dir).isDirectory()) + error('not a directory: ' + dir); + + process.chdir(dir); +}; +exports.cd = wrap('cd', _cd); + +//@ +//@ ### pwd() +//@ Returns the current directory. +function _pwd(options) { + var pwd = path.resolve(process.cwd()); + return ShellString(pwd); +}; +exports.pwd = wrap('pwd', _pwd); + + +//@ +//@ ### ls([options ,] path [,path ...]) +//@ ### ls([options ,] path_array) +//@ Available options: +//@ +//@ + `-R`: recursive +//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ ls('projs/*.js'); +//@ ls('-R', '/users/me', '/tmp'); +//@ ls('-R', ['/users/me', '/tmp']); // same as above +//@ ``` +//@ +//@ Returns array of files in the given path, or in current directory if no path provided. +function _ls(options, paths) { + options = parseOptions(options, { + 'R': 'recursive', + 'A': 'all', + 'a': 'all_deprecated' + }); + + if (options.all_deprecated) { + // We won't support the -a option as it's hard to image why it's useful + // (it includes '.' and '..' in addition to '.*' files) + // For backwards compatibility we'll dump a deprecated message and proceed as before + log('ls: Option -a is deprecated. Use -A instead'); + options.all = true; + } + + if (!paths) + paths = ['.']; + else if (typeof paths === 'object') + paths = paths; // assume array + else if (typeof paths === 'string') + paths = [].slice.call(arguments, 1); + + var list = []; + + // Conditionally pushes file to list - returns true if pushed, false otherwise + // (e.g. prevents hidden files to be included unless explicitly told so) + function pushFile(file, query) { + // hidden file? + if (path.basename(file)[0] === '.') { + // not explicitly asking for hidden files? + if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1)) + return false; + } + + if (platform === 'win') + file = file.replace(/\\/g, '/'); + + list.push(file); + return true; + } + + paths.forEach(function(p) { + if (fs.existsSync(p)) { + // Simple file? + if (fs.statSync(p).isFile()) { + pushFile(p, p); + return; // continue + } + + // Simple dir? + if (fs.statSync(p).isDirectory()) { + // Iterate over p contents + fs.readdirSync(p).forEach(function(file) { + if (!pushFile(file, p)) + return; + + // Recursive? + if (options.recursive) { + var oldDir = _pwd(); + _cd('', p); + if (fs.statSync(file).isDirectory()) + list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*')); + _cd('', oldDir); + } + }); + return; // continue + } + } + + // p does not exist - possible wildcard present + + var basename = path.basename(p); + var dirname = path.dirname(p); + // Wildcard present on an existing dir? (e.g. '/tmp/*.js') + if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) { + // Escape special regular expression chars + var regexp = basename.replace(/(\^|\$|\(|\)|\<|\>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1'); + // Translates wildcard into regex + regexp = '^' + regexp.replace(/\*/g, '.*') + '$'; + // Iterate over directory contents + fs.readdirSync(dirname).forEach(function(file) { + if (file.match(new RegExp(regexp))) { + if (!pushFile(path.normalize(dirname+'/'+file), basename)) + return; + + // Recursive? + if (options.recursive) { + var pp = dirname + '/' + file; + if (fs.statSync(pp).isDirectory()) + list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*')); + } // recursive + } // if file matches + }); // forEach + return; + } + + error('no such file or directory: ' + p, true); + }); + + return list; +}; +exports.ls = wrap('ls', _ls); + + +//@ +//@ ### find(path [,path ...]) +//@ ### find(path_array) +//@ Examples: +//@ +//@ ```javascript +//@ find('src', 'lib'); +//@ find(['src', 'lib']); // same as above +//@ find('.').filter(function(file) { return file.match(/\.js$/); }); +//@ ``` +//@ +//@ Returns array of all files (however deep) in the given paths. +//@ +//@ The main difference from `ls('-R', path)` is that the resulting file names +//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`. +function _find(options, paths) { + if (!paths) + error('no path specified'); + else if (typeof paths === 'object') + paths = paths; // assume array + else if (typeof paths === 'string') + paths = [].slice.call(arguments, 1); + + var list = []; + + function pushFile(file) { + if (platform === 'win') + file = file.replace(/\\/g, '/'); + list.push(file); + } + + // why not simply do ls('-R', paths)? because the output wouldn't give the base dirs + // to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory + + paths.forEach(function(file) { + pushFile(file); + + if (fs.statSync(file).isDirectory()) { + _ls('-RA', file+'/*').forEach(function(subfile) { + pushFile(subfile); + }); + } + }); + + return list; +} +exports.find = wrap('find', _find); + + +//@ +//@ ### cp([options ,] source [,source ...], dest) +//@ ### cp([options ,] source_array, dest) +//@ Available options: +//@ +//@ + `-f`: force +//@ + `-r, -R`: recursive +//@ +//@ Examples: +//@ +//@ ```javascript +//@ cp('file1', 'dir1'); +//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); +//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above +//@ ``` +//@ +//@ Copies files. The wildcard `*` is accepted. +function _cp(options, sources, dest) { + options = parseOptions(options, { + 'f': 'force', + 'R': 'recursive', + 'r': 'recursive' + }); + + // Get sources, dest + if (arguments.length < 3) { + error('missing and/or '); + } else if (arguments.length > 3) { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } else if (typeof sources === 'string') { + sources = [sources]; + } else if ('length' in sources) { + sources = sources; // no-op for array + } else { + error('invalid arguments'); + } + + // Dest is not existing dir, but multiple sources given + if ((!fs.existsSync(dest) || !fs.statSync(dest).isDirectory()) && sources.length > 1) + error('dest is not a directory (too many sources)'); + + // Dest is an existing file, but no -f given + if (fs.existsSync(dest) && fs.statSync(dest).isFile() && !options.force) + error('dest file already exists: ' + dest); + + // Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*" + // (see Github issue #15) + if (options.recursive) { + sources.forEach(function(src, i) { + if (src[src.length - 1] === '/') + sources[i] += '*'; + }); + } + + sources = expand(sources); + + sources.forEach(function(src) { + if (!fs.existsSync(src)) { + error('no such file or directory: '+src, true); + return; // skip file + } + + // If here, src exists + + if (fs.statSync(src).isDirectory()) { + if (!options.recursive) { + // Non-Recursive + log(src + ' is a directory (not copied)'); + } else { + // Recursive + // 'cp /a/source dest' should create 'source' in 'dest' + var newDest = dest+'/'+path.basename(src), + checkDir = fs.statSync(src); + try { + fs.mkdirSync(newDest, checkDir.mode); + } catch (e) { + //if the directory already exists, that's okay + if (e.code !== 'EEXIST') throw e; + } + cpdirSyncRecursive(src, newDest, {force: options.force}); + } + return; // done with dir + } + + // If here, src is a file + + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) + thisDest = path.normalize(dest + '/' + path.basename(src)); + + if (fs.existsSync(thisDest) && !options.force) { + error('dest file already exists: ' + thisDest, true); + return; // skip file + } + + copyFileSync(src, thisDest); + }); // forEach(src) +}; // cp +exports.cp = wrap('cp', _cp); + +//@ +//@ ### rm([options ,] file [, file ...]) +//@ ### rm([options ,] file_array) +//@ Available options: +//@ +//@ + `-f`: force +//@ + `-r, -R`: recursive +//@ +//@ Examples: +//@ +//@ ```javascript +//@ rm('-rf', '/tmp/*'); +//@ rm('some_file.txt', 'another_file.txt'); +//@ rm(['some_file.txt', 'another_file.txt']); // same as above +//@ ``` +//@ +//@ Removes files. The wildcard `*` is accepted. +function _rm(options, files) { + options = parseOptions(options, { + 'f': 'force', + 'r': 'recursive', + 'R': 'recursive' + }); + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 1); + // if it's array leave it as it is + + files = expand(files); + + files.forEach(function(file) { + if (!fs.existsSync(file)) { + // Path does not exist, no force flag given + if (!options.force) + error('no such file or directory: '+file, true); + + return; // skip file + } + + // If here, path exists + + // Remove simple file + if (fs.statSync(file).isFile()) { + + // Do not check for file writing permissions + if (options.force) { + _unlinkSync(file); + return; + } + + if (isWriteable(file)) + _unlinkSync(file); + else + error('permission denied: '+file, true); + + return; + } // simple file + + // Path is an existing directory, but no -r flag given + if (fs.statSync(file).isDirectory() && !options.recursive) { + error('path is a directory', true); + return; // skip path + } + + // Recursively remove existing directory + if (fs.statSync(file).isDirectory() && options.recursive) { + rmdirSyncRecursive(file, options.force); + } + }); // forEach(file) +}; // rm +exports.rm = wrap('rm', _rm); + +//@ +//@ ### mv(source [, source ...], dest') +//@ ### mv(source_array, dest') +//@ Available options: +//@ +//@ + `f`: force +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mv('-f', 'file', 'dir/'); +//@ mv('file1', 'file2', 'dir/'); +//@ mv(['file1', 'file2'], 'dir/'); // same as above +//@ ``` +//@ +//@ Moves files. The wildcard `*` is accepted. +function _mv(options, sources, dest) { + options = parseOptions(options, { + 'f': 'force' + }); + + // Get sources, dest + if (arguments.length < 3) { + error('missing and/or '); + } else if (arguments.length > 3) { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } else if (typeof sources === 'string') { + sources = [sources]; + } else if ('length' in sources) { + sources = sources; // no-op for array + } else { + error('invalid arguments'); + } + + sources = expand(sources); + + // Dest is not existing dir, but multiple sources given + if ((!fs.existsSync(dest) || !fs.statSync(dest).isDirectory()) && sources.length > 1) + error('dest is not a directory (too many sources)'); + + // Dest is an existing file, but no -f given + if (fs.existsSync(dest) && fs.statSync(dest).isFile() && !options.force) + error('dest file already exists: ' + dest); + + sources.forEach(function(src) { + if (!fs.existsSync(src)) { + error('no such file or directory: '+src, true); + return; // skip file + } + + // If here, src exists + + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) + thisDest = path.normalize(dest + '/' + path.basename(src)); + + if (fs.existsSync(thisDest) && !options.force) { + error('dest file already exists: ' + thisDest, true); + return; // skip file + } + + if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { + error('cannot move to self: '+src, true); + return; // skip file + } + + fs.renameSync(src, thisDest); + }); // forEach(src) +}; // mv +exports.mv = wrap('mv', _mv); + +//@ +//@ ### mkdir([options ,] dir [, dir ...]) +//@ ### mkdir([options ,] dir_array) +//@ Available options: +//@ +//@ + `p`: full path (will create intermediate dirs if necessary) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); +//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above +//@ ``` +//@ +//@ Creates directories. +function _mkdir(options, dirs) { + options = parseOptions(options, { + 'p': 'fullpath' + }); + if (!dirs) + error('no paths given'); + + if (typeof dirs === 'string') + dirs = [].slice.call(arguments, 1); + // if it's array leave it as it is + + dirs.forEach(function(dir) { + if (fs.existsSync(dir)) { + if (!options.fullpath) + error('path already exists: ' + dir, true); + return; // skip dir + } + + // Base dir does not exist, and no -p option given + var baseDir = path.dirname(dir); + if (!fs.existsSync(baseDir) && !options.fullpath) { + error('no such file or directory: ' + baseDir, true); + return; // skip dir + } + + if (options.fullpath) + mkdirSyncRecursive(dir); + else + fs.mkdirSync(dir, 0777); + }); +}; // mkdir +exports.mkdir = wrap('mkdir', _mkdir); + +//@ +//@ ### test(expression) +//@ Available expression primaries: +//@ +//@ + `'-b', 'path'`: true if path is a block device +//@ + `'-c', 'path'`: true if path is a character device +//@ + `'-d', 'path'`: true if path is a directory +//@ + `'-e', 'path'`: true if path exists +//@ + `'-f', 'path'`: true if path is a regular file +//@ + `'-L', 'path'`: true if path is a symboilc link +//@ + `'-p', 'path'`: true if path is a pipe (FIFO) +//@ + `'-S', 'path'`: true if path is a socket +//@ +//@ Examples: +//@ +//@ ```javascript +//@ if (test('-d', path)) { /* do something with dir */ }; +//@ if (!test('-f', path)) continue; // skip if it's a regular file +//@ ``` +//@ +//@ Evaluates expression using the available primaries and returns corresponding value. +function _test(options, path) { + if (!path) + error('no path given'); + + // hack - only works with unary primaries + options = parseOptions(options, { + 'b': 'block', + 'c': 'character', + 'd': 'directory', + 'e': 'exists', + 'f': 'file', + 'L': 'link', + 'p': 'pipe', + 'S': 'socket' + }); + + var canInterpret = false; + for (var key in options) + if (options[key] === true) { + canInterpret = true; + break; + } + + if (!canInterpret) + error('could not interpret expression'); + + if (!fs.existsSync(path)) + return false; + + if (options.exists) + return true; + + if (options.link) + return fs.lstatSync(path).isSymbolicLink(); + + var stats = fs.statSync(path); + + if (options.block) + return stats.isBlockDevice(); + + if (options.character) + return stats.isCharacterDevice(); + + if (options.directory) + return stats.isDirectory(); + + if (options.file) + return stats.isFile(); + + if (options.pipe) + return stats.isFIFO(); + + if (options.socket) + return stats.isSocket() +}; // test +exports.test = wrap('test', _test); + + +//@ +//@ ### cat(file [, file ...]) +//@ ### cat(file_array) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var str = cat('file*.txt'); +//@ var str = cat('file1', 'file2'); +//@ var str = cat(['file1', 'file2']); // same as above +//@ ``` +//@ +//@ Returns a string containing the given file, or a concatenated string +//@ containing the files if more than one file is given (a new line character is +//@ introduced between each file). Wildcard `*` accepted. +function _cat(options, files) { + var cat = ''; + + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 1); + // if it's array leave it as it is + + files = expand(files); + + files.forEach(function(file) { + if (!fs.existsSync(file)) + error('no such file or directory: ' + file); + + cat += fs.readFileSync(file, 'utf8') + '\n'; + }); + + if (cat[cat.length-1] === '\n') + cat = cat.substring(0, cat.length-1); + + return ShellString(cat); +}; +exports.cat = wrap('cat', _cat); + +//@ +//@ ### 'string'.to(file) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ cat('input.txt').to('output.txt'); +//@ ``` +//@ +//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as +//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ +function _to(options, file) { + if (!file) + error('wrong arguments'); + + if (!fs.existsSync( path.dirname(file) )) + error('no such file or directory: ' + path.dirname(file)); + + try { + fs.writeFileSync(file, this.toString(), 'utf8'); + } catch(e) { + error('could not write to file (code '+e.code+'): '+file, true); + } +}; +// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings. +// For now, this is a dummy function to bookmark places we need such strings +function ShellString(str) { + return str; +} +String.prototype.to = wrap('to', _to); + +//@ +//@ ### sed([options ,] search_regex, replace_str, file) +//@ Available options: +//@ +//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ +//@ +//@ Examples: +//@ +//@ ```javascript +//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); +//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); +//@ ``` +//@ +//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input +//@ using the given search regex and replacement string. Returns the new string after replacement. +function _sed(options, regex, replacement, file) { + options = parseOptions(options, { + 'i': 'inplace' + }); + + if (typeof replacement === 'string') + replacement = replacement; // no-op + else if (typeof replacement === 'number') + replacement = replacement.toString(); // fallback + else + error('invalid replacement string'); + + if (!file) + error('no file given'); + + if (!fs.existsSync(file)) + error('no such file or directory: ' + file); + + var result = fs.readFileSync(file, 'utf8').replace(regex, replacement); + if (options.inplace) + fs.writeFileSync(file, result, 'utf8'); + + return ShellString(result); +}; +exports.sed = wrap('sed', _sed); + +//@ +//@ ### grep([options ,] regex_filter, file [, file ...]) +//@ ### grep([options ,] regex_filter, file_array) +//@ Available options: +//@ +//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); +//@ grep('GLOBAL_VARIABLE', '*.js'); +//@ ``` +//@ +//@ Reads input string from given files and returns a string containing all lines of the +//@ file that match the given `regex_filter`. Wildcard `*` accepted. +function _grep(options, regex, files) { + options = parseOptions(options, { + 'v': 'inverse' + }); + + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 2); + // if it's array leave it as it is + + files = expand(files); + + var grep = ''; + files.forEach(function(file) { + if (!fs.existsSync(file)) { + error('no such file or directory: ' + file, true); + return; + } + + var contents = fs.readFileSync(file, 'utf8'), + lines = contents.split(/\r*\n/); + lines.forEach(function(line) { + var matched = line.match(regex); + if ((options.inverse && !matched) || (!options.inverse && matched)) + grep += line + '\n'; + }); + }); + + return ShellString(grep); +}; +exports.grep = wrap('grep', _grep); + + +//@ +//@ ### which(command) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var nodeExec = which('node'); +//@ ``` +//@ +//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. +//@ Returns string containing the absolute path to the command. +function _which(options, cmd) { + if (!cmd) + error('must specify command'); + + var pathEnv = process.env.path || process.env.Path || process.env.PATH, + pathArray = splitPath(pathEnv), + where = null; + + // No relative/absolute paths provided? + if (cmd.search(/\//) === -1) { + // Search for command in PATH + pathArray.forEach(function(dir) { + if (where) + return; // already found it + + var attempt = path.resolve(dir + '/' + cmd); + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + + if (platform === 'win') { + var baseAttempt = attempt; + attempt = baseAttempt + '.exe'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + attempt = baseAttempt + '.cmd'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + attempt = baseAttempt + '.bat'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + } // if 'win' + }); + } + + // Command not found anywhere? + if (!fs.existsSync(cmd) && !where) + return null; + + where = where || path.resolve(cmd); + + return ShellString(where); +}; +exports.which = wrap('which', _which); + +//@ +//@ ### echo(string [,string ...]) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ echo('hello world'); +//@ var str = echo('hello world'); +//@ ``` +//@ +//@ Prints string to stdout, and returns string with additional utility methods +//@ like `.to()`. +function _echo() { + var messages = [].slice.call(arguments, 0); + console.log.apply(this, messages); + return ShellString(messages.join(' ')); +}; +exports.echo = _echo; // don't wrap() as it could parse '-options' + +//@ +//@ ### exit(code) +//@ Exits the current process with the given exit code. +exports.exit = process.exit; + +//@ +//@ ### env['VAR_NAME'] +//@ Object containing environment variables (both getter and setter). Shortcut to process.env. +exports.env = process.env; + +//@ +//@ ### exec(command [, options] [, callback]) +//@ Available options (all `false` by default): +//@ +//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided. +//@ + `silent`: Do not echo program output to console. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var version = exec('node --version', {silent:true}).output; +//@ +//@ var child = exec('some_long_running_process', {async:true}); +//@ child.stdout.on('data', function(data) { +//@ /* ... do something with data ... */ +//@ }); +//@ +//@ exec('some_long_running_process', function(code, output) { +//@ console.log('Exit code:', code); +//@ console.log('Program output:', output); +//@ }); +//@ ``` +//@ +//@ Executes the given `command` _synchronously_, unless otherwise specified. +//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's +//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and +//@ the `callback` gets the arguments `(code, output)`. +//@ +//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as +//@ the current synchronous implementation uses a lot of CPU. This should be getting +//@ fixed soon. +function _exec(command, options, callback) { + if (!command) + error('must specify command'); + + if (typeof options === 'function') { + callback = options; + options = { async: true }; + } + + options = extend({ + silent: state.silent, + async: false + }, options); + + if (options.async) + return execAsync(command, options, callback); + else + return execSync(command, options); +}; +exports.exec = wrap('exec', _exec, {notUnix:true}); + + + + +//@ +//@ ## Non-Unix commands +//@ + + + + + + +//@ +//@ ### tempdir() +//@ Searches and returns string containing a writeable, platform-dependent temporary directory. +//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). +exports.tempdir = wrap('tempdir', tempDir); + + +//@ +//@ ### error() +//@ Tests if error occurred in the last command. Returns `null` if no error occurred, +//@ otherwise returns string explaining the error +exports.error = function() { + return state.error; +} + +//@ +//@ ### silent([state]) +//@ Example: +//@ +//@ ```javascript +//@ var silentState = silent(); +//@ silent(true); +//@ /* ... */ +//@ silent(silentState); // restore old silent state +//@ ``` +//@ +//@ Suppresses all command output if `state = true`, except for `echo()` calls. +//@ Returns state if no arguments given. +exports.silent = function(_state) { + if (typeof _state !== 'boolean') + return state.silent; + + state.silent = _state; +} + + +//@ +//@ ## Deprecated +//@ + + + + +//@ +//@ ### exists(path [, path ...]) +//@ ### exists(path_array) +//@ +//@ _This function is being deprecated. Use `test()` instead._ +//@ +//@ Returns true if all the given paths exist. +function _exists(options, paths) { + deprecate('exists', 'Use test() instead.'); + + if (!paths) + error('no paths given'); + + if (typeof paths === 'string') + paths = [].slice.call(arguments, 1); + // if it's array leave it as it is + + var exists = true; + paths.forEach(function(p) { + if (!fs.existsSync(p)) + exists = false; + }); + + return exists; +}; +exports.exists = wrap('exists', _exists); + + +//@ +//@ ### verbose() +//@ +//@ _This function is being deprecated. Use `silent(false) instead.`_ +//@ +//@ Enables all output (default) +exports.verbose = function() { + deprecate('verbose', 'Use silent(false) instead.'); + + state.silent = false; +} + + + + + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// +// Auxiliary functions (internal use only) +// + +function log() { + if (!state.silent) + console.log.apply(this, arguments); +} + +function deprecate(what, msg) { + console.log('*** ShellJS.'+what+': This function is deprecated.', msg); +} + +function write(msg) { + if (!state.silent) + process.stdout.write(msg); +} + +// Shows error message. Throws unless '_continue = true'. +function error(msg, _continue) { + if (state.error === null) + state.error = ''; + state.error += state.currentCmd + ': ' + msg + '\n'; + + log(state.error); + + if (!_continue) + throw ''; +} + +// Returns {'alice': true, 'bob': false} when passed: +// parseOptions('-a', {'a':'alice', 'b':'bob'}); +function parseOptions(str, map) { + if (!map) + error('parseOptions() internal error: no map given'); + + // All options are false by default + var options = {}; + for (var letter in map) + options[map[letter]] = false; + + if (!str) + return options; // defaults + + if (typeof str !== 'string') + error('parseOptions() internal error: wrong str'); + + // e.g. match[1] = 'Rf' for str = '-Rf' + var match = str.match(/^\-(.+)/); + if (!match) + return options; + + // e.g. chars = ['R', 'f'] + var chars = match[1].split(''); + + chars.forEach(function(char) { + if (char in map) + options[map[char]] = true; + else + error('option not recognized: '+char); + }); + + return options; +} + +// Common wrapper for all Unix-like commands +function wrap(cmd, fn, options) { + return function() { + var retValue = null; + + state.currentCmd = cmd; + state.error = null; + + try { + var args = [].slice.call(arguments, 0); + + if (options && options.notUnix) { + retValue = fn.apply(this, args); + } else { + if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-') + args.unshift(''); // only add dummy option if '-option' not already present + retValue = fn.apply(this, args); + } + } catch (e) { + if (!state.error) { + // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... + console.log('shell.js: internal error'); + console.log(e.stack || e); + process.exit(1); + } + if (state.fatal) + throw e; + } + + state.currentCmd = 'shell.js'; + return retValue; + } +} // wrap + +// Buffered file copy, synchronous +// (Using readFileSync() + writeFileSync() could easily cause a memory overflow +// with large files) +function copyFileSync(srcFile, destFile) { + if (!fs.existsSync(srcFile)) + error('copyFileSync: no such file or directory: ' + srcFile); + + var BUF_LENGTH = 64*1024, + buf = new Buffer(BUF_LENGTH), + bytesRead = BUF_LENGTH, + pos = 0, + fdr = null, + fdw = null; + + try { + fdr = fs.openSync(srcFile, 'r'); + } catch(e) { + error('copyFileSync: could not read src file ('+srcFile+')'); + } + + try { + fdw = fs.openSync(destFile, 'w'); + } catch(e) { + error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile); + } + + while (bytesRead === BUF_LENGTH) { + bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos); + fs.writeSync(fdw, buf, 0, bytesRead); + pos += bytesRead; + } + + fs.closeSync(fdr); + fs.closeSync(fdw); +} + +// Recursively copies 'sourceDir' into 'destDir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function cpdirSyncRecursive(sourceDir, destDir, opts) { + if (!opts) opts = {}; + + /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ + var checkDir = fs.statSync(sourceDir); + try { + fs.mkdirSync(destDir, checkDir.mode); + } catch (e) { + //if the directory already exists, that's okay + if (e.code !== 'EEXIST') throw e; + } + + var files = fs.readdirSync(sourceDir); + + for(var i = 0; i < files.length; i++) { + var currFile = fs.lstatSync(sourceDir + "/" + files[i]); + + if (currFile.isDirectory()) { + /* recursion this thing right on back. */ + cpdirSyncRecursive(sourceDir + "/" + files[i], destDir + "/" + files[i], opts); + } else if (currFile.isSymbolicLink()) { + var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]); + fs.symlinkSync(symlinkFull, destDir + "/" + files[i]); + } else { + /* At this point, we've hit a file actually worth copying... so copy it on over. */ + if (fs.existsSync(destDir + "/" + files[i]) && !opts.force) { + log('skipping existing file: ' + files[i]); + } else { + copyFileSync(sourceDir + "/" + files[i], destDir + "/" + files[i]); + } + } + + } // for files +}; // cpdirSyncRecursive + +// Recursively removes 'dir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function rmdirSyncRecursive(dir, force) { + var files; + + files = fs.readdirSync(dir); + + // Loop through and delete everything in the sub-tree after checking it + for(var i = 0; i < files.length; i++) { + var file = dir + "/" + files[i], + currFile = fs.lstatSync(file); + + if(currFile.isDirectory()) { // Recursive function back to the beginning + rmdirSyncRecursive(file, force); + } + + else if(currFile.isSymbolicLink()) { // Unlink symlinks + if (force || isWriteable(file)) { + try { + _unlinkSync(file); + } catch (e) { + error('could not remove file (code '+e.code+'): ' + file, true); + } + } + } + + else // Assume it's a file - perhaps a try/catch belongs here? + if (force || isWriteable(file)) { + try { + _unlinkSync(file); + } catch (e) { + error('could not remove file (code '+e.code+'): ' + file, true); + } + } + } + + // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. + // Huzzah for the shopkeep. + + var result; + try { + result = fs.rmdirSync(dir); + } catch(e) { + error('could not remove directory (code '+e.code+'): ' + dir, true); + } + + return result; +}; // rmdirSyncRecursive + +// Recursively creates 'dir' +function mkdirSyncRecursive(dir) { + var baseDir = path.dirname(dir); + + // Base dir exists, no recursion necessary + if (fs.existsSync(baseDir)) { + fs.mkdirSync(dir, 0777); + return; + } + + // Base dir does not exist, go recursive + mkdirSyncRecursive(baseDir); + + // Base dir created, can create dir + fs.mkdirSync(dir, 0777); +}; + +// e.g. 'makerjs_a5f185d0443ca...' +function randomFileName() { + function randomHash(count) { + if (count === 1) + return parseInt(16*Math.random()).toString(16); + else { + var hash = ''; + for (var i=0; i&1'; // works on both win/unix + + var script = + "var child = require('child_process'), \ + fs = require('fs'); \ + child.exec('"+escape(cmd)+"', {env: process.env}, function(err) { \ + fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0'); \ + });"; + + if (fs.existsSync(scriptFile)) _unlinkSync(scriptFile); + if (fs.existsSync(stdoutFile)) _unlinkSync(stdoutFile); + if (fs.existsSync(codeFile)) _unlinkSync(codeFile); + + fs.writeFileSync(scriptFile, script); + child.exec('node '+scriptFile, { + env: process.env, + cwd: exports.pwd() + }); + + // The wait loop + // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage + // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing + // CPU usage, though apparently not so much on Windows) + while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }; + while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }; + + // At this point codeFile exists, but it's not necessarily flushed yet. + // Keep reading it until it is. + var code = parseInt(''); + while (isNaN(code)) + code = parseInt(fs.readFileSync(codeFile, 'utf8')); + + var stdout = fs.readFileSync(stdoutFile, 'utf8'); + + // No biggie if we can't erase the files now -- they're in a temp dir anyway + try { _unlinkSync(scriptFile); } catch(e) {}; + try { _unlinkSync(stdoutFile); } catch(e) {}; + try { _unlinkSync(codeFile); } catch(e) {}; + try { _unlinkSync(sleepFile); } catch(e) {}; + + // True if successful, false if not + var obj = { + code: code, + output: stdout + }; + return obj; +} // execSync() + +// Expands wildcards with matching file names. For a given array of file names 'list', returns +// another array containing all file names as per ls(list[i]). +// For example: +// expand(['file*.js']) = ['file1.js', 'file2.js', ...] +// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) +function expand(list) { + var expanded = []; + list.forEach(function(listEl) { + // Wildcard present? + if (listEl.search(/\*/) > -1) { + _ls('', listEl).forEach(function(file) { + expanded.push(file); + }); + } else { + expanded.push(listEl); + } + }); + return expanded; +} + +// Cross-platform method for splitting environment PATH variables +function splitPath(p) { + if (!p) + return []; + + if (platform === 'win') + return p.split(';'); + else + return p.split(':'); +} + +// extend(target_obj, source_obj1 [, source_obj2 ...]) +// Shallow extend, e.g.: +// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3} +function extend(target) { + var sources = [].slice.call(arguments, 1); + sources.forEach(function(source) { + for (var key in source) + target[key] = source[key]; + }); + + return target; +} + +// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. +// file can be unlinked even if it's read-only, see joyent/node#3006 +function _unlinkSync(file) { + try { + fs.unlinkSync(file); + } catch(e) { + // Try to override file permission + if (e.code === 'EPERM') { + fs.chmodSync(file, '0666'); + fs.unlinkSync(file); + } else { + throw e; + } + } +} + +// Hack to determine if file has write permissions for current user +// Avoids having to check user, group, etc, but it's probably slow +function isWriteable(file) { + var writePermission = true; + try { + var __fd = fs.openSync(file, 'a'); + fs.closeSync(__fd); + } catch(e) { + writePermission = false; + } + + return writePermission; +} diff --git a/enyo/tools/node_modules/shelljs/test/.npmignore b/enyo/tools/node_modules/shelljs/test/.npmignore new file mode 100644 index 0000000..a1632ab --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/.npmignore @@ -0,0 +1,2 @@ +tmp/ + diff --git a/enyo/tools/node_modules/shelljs/test/cat.js b/enyo/tools/node_modules/shelljs/test/cat.js new file mode 100644 index 0000000..cd73543 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/cat.js @@ -0,0 +1,57 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// save current dir +var cur = shell.pwd(); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.cat(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.cat('/adsfasdf'); // file does not exist +assert.ok(shell.error()); + +// +// Valids +// + +// simple +var result = shell.cat('resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'test1'); + +// multiple files +var result = shell.cat('resources/file2', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'test2\ntest1'); + +// multiple files, array syntax +var result = shell.cat(['resources/file2', 'resources/file1']); +assert.equal(shell.error(), null); +assert.equal(result, 'test2\ntest1'); + +var result = shell.cat('resources/file*.txt'); +assert.equal(shell.error(), null); +assert.ok(result.search('test1') > -1); // file order might be random +assert.ok(result.search('test2') > -1); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/cd.js b/enyo/tools/node_modules/shelljs/test/cd.js new file mode 100644 index 0000000..0852ec7 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/cd.js @@ -0,0 +1,64 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// save current dir +var cur = shell.pwd(); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.cd(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.cd('/adsfasdf'); // dir does not exist +assert.ok(shell.error()); + +assert.equal(fs.existsSync('resources/file1'), true); // sanity check +shell.cd('resources/file1'); // file, not dir +assert.ok(shell.error()); + +// +// Valids +// + +shell.cd(cur); +shell.cd('tmp'); +assert.equal(shell.error(), null); +assert.equal(path.basename(process.cwd()), 'tmp'); + +shell.cd(cur); +shell.cd('/'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), path.resolve('/')); + +// cd + other commands + +shell.cd(cur); +shell.rm('-f', 'tmp/*'); +assert.equal(fs.existsSync('tmp/file1'), false); +shell.cd('resources'); +assert.equal(shell.error(), null); +shell.cp('file1', '../tmp'); +assert.equal(shell.error(), null); +shell.cd('../tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), true); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/cp.js b/enyo/tools/node_modules/shelljs/test/cp.js new file mode 100644 index 0000000..7e32c64 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/cp.js @@ -0,0 +1,130 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.cp(); +assert.ok(shell.error()); + +shell.cp('file1'); +assert.ok(shell.error()); + +shell.cp('-f'); +assert.ok(shell.error()); + +shell.rm('-rf', 'tmp/*'); +shell.cp('-@', 'resources/file1', 'tmp/file1'); // option not supported, files OK +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), false); + +shell.cp('-Z', 'asdfasdf', 'tmp/file2'); // option not supported, files NOT OK +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file2'), false); + +shell.cp('asdfasdf', 'tmp'); // source does not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/asdfasdf'), false); + +shell.cp('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 2); +assert.equal(fs.existsSync('tmp/asdfasdf1'), false); +assert.equal(fs.existsSync('tmp/asdfasdf2'), false); + +shell.cp('asdfasdf1', 'asdfasdf2', 'resources/file1'); // too many sources (dest is file) +assert.ok(shell.error()); + +shell.cp('resources/file1', 'resources/file2'); // dest already exists +assert.ok(shell.error()); + +shell.cp('resources/file1', 'resources/file2', 'tmp/a_file'); // too many sources +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/a_file'), false); + +// +// Valids +// + +// simple - to dir +shell.cp('resources/file1', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); + +// simple - to file +shell.cp('resources/file2', 'tmp/file2'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file2'), true); + +// simple - file list +shell.rm('-rf', 'tmp/*'); +shell.cp('resources/file1', 'resources/file2', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +// simple - file list, array syntax +shell.rm('-rf', 'tmp/*'); +shell.cp(['resources/file1', 'resources/file2'], 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +shell.cp('resources/file2', 'tmp/file3'); +assert.equal(fs.existsSync('tmp/file3'), true); +shell.cp('-f', 'resources/file2', 'tmp/file3'); // file exists, but -f specified +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file3'), true); + +// wildcard +shell.rm('tmp/file1', 'tmp/file2'); +shell.cp('resources/file*', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +//recursive, nothing exists +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(JSON.stringify(shell.ls('-R', 'resources/cp')), JSON.stringify(shell.ls('-R', 'tmp/cp'))); + +//recursive, nothing exists, source ends in '/' (see Github issue #15) +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp/', 'tmp/'); +assert.equal(shell.error(), null); +assert.equal(JSON.stringify(shell.ls('-R', 'resources/cp')), JSON.stringify(shell.ls('-R', 'tmp'))); + +//recursive, everything exists, no force flag +shell.rm('-rf', 'tmp/*') +shell.cp('-R', 'resources/cp', 'tmp'); +shell.cp('-R', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); // crash test only + +//recursive, everything exists, with force flag +shell.rm('-rf', 'tmp/*') +shell.cp('-R', 'resources/cp', 'tmp'); +'changing things around'.to('tmp/cp/dir_a/z'); +assert.notEqual(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // before cp +shell.cp('-Rf', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // after cp + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/echo.js b/enyo/tools/node_modules/shelljs/test/echo.js new file mode 100644 index 0000000..b6f2db1 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/echo.js @@ -0,0 +1,50 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'), + child = require('child_process'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Valids +// + + +// From here on we use child.exec() to intercept the stdout + + +// simple test with defaults +shell.mkdir('-p', 'tmp'); +var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); echo("-asdf", "111");'; // test '-' bug (see issue #20) +script.to(file); +child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout === '-asdf 111\n' || stdout === '-asdf 111\nundefined\n'); // 'undefined' for v0.4 + + // simple test with silent(true) + shell.mkdir('-p', 'tmp'); + var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); silent(true); echo(555);'; + script.to(file); + child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout === '555\n' || stdout === '555\nundefined\n'); // 'undefined' for v0.4 + + theEnd(); + }); +}); + +function theEnd() { + shell.exit(123); +} diff --git a/enyo/tools/node_modules/shelljs/test/env.js b/enyo/tools/node_modules/shelljs/test/env.js new file mode 100644 index 0000000..813ce27 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/env.js @@ -0,0 +1,19 @@ +var shell = require('..'); + +var assert = require('assert'); + +shell.silent(true); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Valids +// + +assert.equal(shell.env['PATH'], process.env['PATH']); + +shell.env['MAKERJS_TEST'] = 'hello world'; +assert.equal(shell.env['MAKERJS_TEST'], process.env['MAKERJS_TEST']); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/exec.js b/enyo/tools/node_modules/shelljs/test/exec.js new file mode 100644 index 0000000..473281b --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/exec.js @@ -0,0 +1,93 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'), + child = require('child_process'); + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// +// Invalids +// + +shell.exec(); +assert.ok(shell.error()); + +var result = shell.exec('asdfasdf'); // could not find command +assert.ok(result.code > 0); + + +// +// Valids +// + +// +// sync +// + +// check if stdout goes to output +var result = shell.exec('node -e \"console.log(1234);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 + +// check if stderr goes to output +var result = shell.exec('node -e \"console.error(1234);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 + +// check if stdout + stderr go to output +var result = shell.exec('node -e \"console.error(1234); console.log(666);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n666\n' || result.output === '1234\n666\nundefined\n'); // 'undefined' for v0.4 + +// check exit code +var result = shell.exec('node -e \"process.exit(12);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 12); + +// interaction with cd +shell.cd('resources/external'); +var result = shell.exec('node node_script.js'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.equal(result.output, 'node_script_1234\n'); +shell.cd('../..'); + +// +// async +// + +// no callback +var c = shell.exec('node -e \"console.log(1234)\"', {async:true}); +assert.equal(shell.error(), null); +assert.ok('stdout' in c, 'async exec returns child process object'); + +// +// callback as 2nd argument +// +shell.exec('node -e \"console.log(5678);\"', function(code, output) { + assert.equal(code, 0); + assert.ok(output === '5678\n' || output === '5678\nundefined\n'); // 'undefined' for v0.4 + + // + // callback as 3rd argument + // + shell.exec('node -e \"console.log(5566);\"', {async:true}, function(code, output) { + assert.equal(code, 0); + assert.ok(output === '5566\n' || output === '5566\nundefined\n'); // 'undefined' for v0.4 + + shell.exit(123); + + }); + +}); + +assert.equal(shell.error(), null); diff --git a/enyo/tools/node_modules/shelljs/test/find.js b/enyo/tools/node_modules/shelljs/test/find.js new file mode 100644 index 0000000..423b82a --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/find.js @@ -0,0 +1,56 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +var result = shell.find(); // no paths given +assert.ok(shell.error()); + +// +// Valids +// + +// current path +shell.cd('resources/find'); +var result = shell.find('.'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('.hidden') > -1, true); +assert.equal(result.indexOf('dir1/dir11/a_dir11') > -1, true); +assert.equal(result.length, 10); +shell.cd('../..') + +// simple path +var result = shell.find('resources/find'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/.hidden') > -1, true); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.length, 10); + +// multiple paths - comma +var result = shell.find('resources/find/dir1', 'resources/find/dir2'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); +assert.equal(result.length, 6); + +// multiple paths - array +var result = shell.find(['resources/find/dir1', 'resources/find/dir2']); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); +assert.equal(result.length, 6); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/grep.js b/enyo/tools/node_modules/shelljs/test/grep.js new file mode 100644 index 0000000..498d353 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/grep.js @@ -0,0 +1,59 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.grep(); +assert.ok(shell.error()); + +shell.grep(/asdf/g); // too few args +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.grep(/asdf/g, '/asdfasdf'); // no such file +assert.ok(shell.error()); + +// +// Valids +// + +var result = shell.grep('line', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result.split('\n').length - 1, 4); + +var result = shell.grep('-v', 'line', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result.split('\n').length - 1, 8); + +var result = shell.grep('line one', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result, 'This is line one\n'); + +// multiple files +var result = shell.grep(/test/, 'resources/file1.txt', 'resources/file2.txt'); +assert.equal(shell.error(), null); +assert.equal(result, 'test1\ntest2\n'); + +// multiple files, array syntax +var result = shell.grep(/test/, ['resources/file1.txt', 'resources/file2.txt']); +assert.equal(shell.error(), null); +assert.equal(result, 'test1\ntest2\n'); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/ls.js b/enyo/tools/node_modules/shelljs/test/ls.js new file mode 100644 index 0000000..c826323 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/ls.js @@ -0,0 +1,202 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +var result = shell.ls('/asdfasdf'); // no such file or dir +assert.ok(shell.error()); +assert.equal(result.length, 0); + +// +// Valids +// + +var result = shell.ls(); +assert.equal(shell.error(), null); + +var result = shell.ls('/'); +assert.equal(shell.error(), null); + +// no args +shell.cd('resources/ls'); +var result = shell.ls(); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.length, 6); +shell.cd('../..'); + +// simple arg +var result = shell.ls('resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.length, 6); + +// no args, 'all' option +shell.cd('resources/ls'); +var result = shell.ls('-A'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('.hidden_file') > -1, true); +assert.equal(result.indexOf('.hidden_dir') > -1, true); +assert.equal(result.length, 8); +shell.cd('../..'); + +// no args, 'all' option +shell.cd('resources/ls'); +var result = shell.ls('-a'); // (deprecated) backwards compatibility test +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('.hidden_file') > -1, true); +assert.equal(result.indexOf('.hidden_dir') > -1, true); +assert.equal(result.length, 8); +shell.cd('../..'); + +// wildcard, simple +var result = shell.ls('resources/ls/*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/file1') > -1, true); +assert.equal(result.indexOf('resources/ls/file2') > -1, true); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); +assert.equal(result.length, 6); + +// wildcard, hidden only +var result = shell.ls('resources/ls/.*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/.hidden_file') > -1, true); +assert.equal(result.indexOf('resources/ls/.hidden_dir') > -1, true); +assert.equal(result.length, 2); + +// wildcard, mid-file +var result = shell.ls('resources/ls/f*le*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 5); +assert.equal(result.indexOf('resources/ls/file1') > -1, true); +assert.equal(result.indexOf('resources/ls/file2') > -1, true); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); + +// wildcard, mid-file with dot (should escape dot for regex) +var result = shell.ls('resources/ls/f*le*.js'); +assert.equal(shell.error(), null); +assert.equal(result.length, 2); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); + +// wildcard, should not do partial matches +var result = shell.ls('resources/ls/*.j'); // shouldn't get .js +assert.equal(shell.error(), null); +assert.equal(result.length, 0); + +// wildcard, all files with extension +var result = shell.ls('resources/ls/*.*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 3); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); + +// wildcard, with additional path +var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir'); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('b_dir') > -1, true); // no wildcard == no path prefix +assert.equal(result.indexOf('nada') > -1, true); // no wildcard == no path prefix + +// wildcard for both paths +var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir/*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); + +// wildcard for both paths, array +var result = shell.ls(['resources/ls/f*le*.js', 'resources/ls/a_dir/*']); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); + +// recursive, no path +shell.cd('resources/ls'); +var result = shell.ls('-R'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); +shell.cd('../..'); + +// recusive, path given +var result = shell.ls('-R', 'resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); + +// recusive, path given - 'all' flag +var result = shell.ls('-RA', 'resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.indexOf('a_dir/.hidden_dir/nada') > -1, true); +assert.equal(result.length, 14); + +// recursive, wildcard +var result = shell.ls('-R', 'resources/ls/*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/mkdir.js b/enyo/tools/node_modules/shelljs/test/mkdir.js new file mode 100644 index 0000000..2bc2a0a --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/mkdir.js @@ -0,0 +1,79 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.mkdir(); +assert.ok(shell.error()); + +var mtime = fs.statSync('tmp').mtime.toString(); +shell.mkdir('tmp'); // dir already exists +assert.ok(shell.error()); +assert.equal(fs.statSync('tmp').mtime.toString(), mtime); // didn't mess with dir + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.mkdir('/asdfasdf/asdfasdf'); // root path does not exist +assert.ok(shell.error()); +assert.equal(fs.existsSync('/asdfasdf'), false); + +// +// Valids +// + +assert.equal(fs.existsSync('tmp/t1'), false); +shell.mkdir('tmp/t1'); // simple dir +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/t1'), true); + +assert.equal(fs.existsSync('tmp/t2'), false); +assert.equal(fs.existsSync('tmp/t3'), false); +shell.mkdir('tmp/t2', 'tmp/t3'); // multiple dirs +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/t2'), true); +assert.equal(fs.existsSync('tmp/t3'), true); + +assert.equal(fs.existsSync('tmp/t1'), true); +assert.equal(fs.existsSync('tmp/t4'), false); +shell.mkdir('tmp/t1', 'tmp/t4'); // one dir exists, one doesn't +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/t1'), true); +assert.equal(fs.existsSync('tmp/t4'), true); + +assert.equal(fs.existsSync('tmp/a'), false); +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', 'tmp/a'); // revert + +// multiple dirs +shell.mkdir('-p', 'tmp/zzza', 'tmp/zzzb', 'tmp/zzzc'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/zzza'), true); +assert.equal(fs.existsSync('tmp/zzzb'), true); +assert.equal(fs.existsSync('tmp/zzzc'), true); + +// multiple dirs, array syntax +shell.mkdir('-p', ['tmp/yyya', 'tmp/yyyb', 'tmp/yyyc']); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/yyya'), true); +assert.equal(fs.existsSync('tmp/yyyb'), true); +assert.equal(fs.existsSync('tmp/yyyc'), true); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/mv.js b/enyo/tools/node_modules/shelljs/test/mv.js new file mode 100644 index 0000000..fd49d33 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/mv.js @@ -0,0 +1,130 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// Prepare tmp/ +shell.cp('resources/*', 'tmp'); + +// +// Invalids +// + +shell.mv(); +assert.ok(shell.error()); + +shell.mv('file1'); +assert.ok(shell.error()); + +shell.mv('-f'); +assert.ok(shell.error()); + +shell.mv('-Z', 'tmp/file1', 'tmp/file1'); // option not supported +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), true); + +shell.mv('asdfasdf', 'tmp'); // source does not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/asdfasdf'), false); + +shell.mv('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 2); +assert.equal(fs.existsSync('tmp/asdfasdf1'), false); +assert.equal(fs.existsSync('tmp/asdfasdf2'), false); + +shell.mv('asdfasdf1', 'asdfasdf2', 'tmp/file1'); // too many sources (dest is file) +assert.ok(shell.error()); + +shell.mv('tmp/file1', 'tmp/file2'); // dest already exists +assert.ok(shell.error()); + +shell.mv('tmp/file1', 'tmp/file2', 'tmp/a_file'); // too many sources (exist, but dest is file) +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/a_file'), false); + +shell.mv('tmp/file*', 'tmp/file1'); // can't use wildcard when dest is file +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); +assert.equal(fs.existsSync('tmp/file1.js'), true); +assert.equal(fs.existsSync('tmp/file2.js'), true); + +// +// Valids +// + +shell.cd('tmp'); + +// handles self OK +shell.mkdir('tmp2'); +shell.mv('*', 'tmp2'); // has to handle self (tmp2 --> tmp2) without throwing error +assert.ok(shell.error()); // there's an error, but not fatal +assert.equal(fs.existsSync('tmp2/file1'), true); // moved OK +shell.mv('tmp2/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); // moved OK + +shell.mv('file1', 'file3'); // one source +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file3'), true); +shell.mv('file3', 'file1'); // revert +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), true); + +// two sources +shell.rm('-rf', 't'); +shell.mkdir('-p', 't'); +shell.mv('file1', 'file2', 't'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), false); +assert.equal(fs.existsSync('t/file1'), true); +assert.equal(fs.existsSync('t/file2'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); +assert.equal(fs.existsSync('file2'), true); + +// two sources, array style +shell.rm('-rf', 't'); +shell.mkdir('-p', 't'); +shell.mv(['file1', 'file2'], 't'); // two sources +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), false); +assert.equal(fs.existsSync('t/file1'), true); +assert.equal(fs.existsSync('t/file2'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); +assert.equal(fs.existsSync('file2'), true); + +shell.mv('file*.js', 't'); // wildcard +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1.js'), false); +assert.equal(fs.existsSync('file2.js'), false); +assert.equal(fs.existsSync('t/file1.js'), true); +assert.equal(fs.existsSync('t/file2.js'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1.js'), true); +assert.equal(fs.existsSync('file2.js'), true); + +shell.mv('-f', 'file1', 'file2'); // dest exists, but -f given +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), true); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/pwd.js b/enyo/tools/node_modules/shelljs/test/pwd.js new file mode 100644 index 0000000..dd4d75c --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/pwd.js @@ -0,0 +1,28 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'); + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Valids +// + +var _pwd = shell.pwd(); +assert.equal(shell.error(), null); +assert.equal(_pwd, path.resolve('.')); + +shell.cd('tmp'); +var _pwd = shell.pwd(); +assert.equal(shell.error(), null); +assert.equal(path.basename(_pwd), 'tmp'); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/resources/a.txt b/enyo/tools/node_modules/shelljs/test/resources/a.txt new file mode 100644 index 0000000..356ce49 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/a.txt @@ -0,0 +1,11 @@ +This is line one +This is line two + +This is line four +. +. +More content here +. +. + +This is line eleven diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/a b/enyo/tools/node_modules/shelljs/test/resources/cp/a new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/cp/a @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/b b/enyo/tools/node_modules/shelljs/test/resources/cp/b new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/cp/b @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js b/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js new file mode 100644 index 0000000..3b2d24a --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js @@ -0,0 +1,2 @@ +console.log('node_script_1234'); + diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/tmp/output b/enyo/tools/node_modules/shelljs/test/resources/external/tmp/output new file mode 100644 index 0000000..e69de29 diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js b/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js new file mode 100644 index 0000000..a77652f --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js @@ -0,0 +1 @@ +throw __dirname; require('../../global.js'); silent(false); exec('node -e "console.log(1234);"', {silent:false}) \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1 b/enyo/tools/node_modules/shelljs/test/resources/file1 new file mode 100644 index 0000000..f079749 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file1 @@ -0,0 +1 @@ +test1 \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1.js b/enyo/tools/node_modules/shelljs/test/resources/file1.js new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file1.js @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1.txt b/enyo/tools/node_modules/shelljs/test/resources/file1.txt new file mode 100644 index 0000000..a5bce3f --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file1.txt @@ -0,0 +1 @@ +test1 diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2 b/enyo/tools/node_modules/shelljs/test/resources/file2 new file mode 100644 index 0000000..d606037 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file2 @@ -0,0 +1 @@ +test2 \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2.js b/enyo/tools/node_modules/shelljs/test/resources/file2.js new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file2.js @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2.txt b/enyo/tools/node_modules/shelljs/test/resources/file2.txt new file mode 100644 index 0000000..180cf83 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/file2.txt @@ -0,0 +1 @@ +test2 diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/.hidden b/enyo/tools/node_modules/shelljs/test/resources/find/.hidden new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/.hidden @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/a b/enyo/tools/node_modules/shelljs/test/resources/find/a new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/a @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/b b/enyo/tools/node_modules/shelljs/test/resources/find/b new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/b @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 b/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada new file mode 100644 index 0000000..5fedf57 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada @@ -0,0 +1 @@ +nada \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file1 b/enyo/tools/node_modules/shelljs/test/resources/ls/file1 new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/file1 @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js b/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file2 b/enyo/tools/node_modules/shelljs/test/resources/ls/file2 new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/file2 @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js b/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js @@ -0,0 +1 @@ +test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped b/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped new file mode 100644 index 0000000..8bd6648 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped @@ -0,0 +1 @@ +asdf diff --git a/enyo/tools/node_modules/shelljs/test/rm.js b/enyo/tools/node_modules/shelljs/test/rm.js new file mode 100644 index 0000000..732950c --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/rm.js @@ -0,0 +1,183 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.rm(); +assert.ok(shell.error()); + +shell.rm('asdfasdf'); // file does not exist +assert.ok(shell.error()); + +shell.rm('-f'); // no file +assert.ok(shell.error()); + +shell.rm('-@', 'resources/file1'); // invalid option +assert.ok(shell.error()); +assert.equal(fs.existsSync('resources/file1'), true); + +// +// Valids +// + +// file does not exist, but -f specified +shell.rm('-f', 'asdfasdf'); +assert.equal(shell.error(), null); + + // simple rm + shell.cp('-f', 'resources/file1', 'tmp/file1'); +assert.equal(fs.existsSync('tmp/file1'), true); +shell.rm('tmp/file1'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), false); + +// recursive dir removal - small-caps '-r' +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-rf', 'tmp/a'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// recursive dir removal - capital '-R' +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', 'tmp/a'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// recursive dir removal - absolute path +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', path.resolve('./tmp/a')); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// wildcard +shell.cp('-f', 'resources/file*', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); +assert.equal(fs.existsSync('tmp/file1.js'), true); +assert.equal(fs.existsSync('tmp/file2.js'), true); +shell.rm('tmp/file*'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), false); +assert.equal(fs.existsSync('tmp/file2'), false); +assert.equal(fs.existsSync('tmp/file1.js'), false); +assert.equal(fs.existsSync('tmp/file2.js'), false); + +// recursive dir removal +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', 'tmp/*'); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 1); +assert.equal(contents[0], '.hidden'); // shouldn't remove hiddden if no .* given + +// recursive dir removal +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', 'tmp/*', 'tmp/.*'); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 0); + +// recursive dir removal - array-syntax +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', ['tmp/*', 'tmp/.*']); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 0); + +// removal of a read-only file (unforced) +shell.mkdir('-p', 'tmp/readonly'); +'asdf'.to('tmp/readonly/file1'); +fs.chmodSync('tmp/readonly/file1', '0444'); // -r--r--r-- +shell.rm('tmp/readonly/file1'); +assert.equal(fs.existsSync('tmp/readonly/file1'), true); // bash's rm always asks before removing read-only files + // here we just assume "no" + +// removal of a read-only file (forced) +shell.mkdir('-p', 'tmp/readonly'); +'asdf'.to('tmp/readonly/file2'); +fs.chmodSync('tmp/readonly/file2', '0444'); // -r--r--r-- +shell.rm('-f', 'tmp/readonly/file2'); +assert.equal(fs.existsSync('tmp/readonly/file2'), false); + +// removal of a tree containing read-only files (unforced) +shell.mkdir('-p', 'tmp/tree2'); +'asdf'.to('tmp/tree2/file1'); +'asdf'.to('tmp/tree2/file2'); +fs.chmodSync('tmp/tree2/file1', '0444'); // -r--r--r-- +shell.rm('-r', 'tmp/tree2'); +assert.equal(fs.existsSync('tmp/tree2/file1'), true); +assert.equal(fs.existsSync('tmp/tree2/file2'), false); + +// removal of a tree containing read-only files (forced) +shell.mkdir('-p', 'tmp/tree'); +'asdf'.to('tmp/tree/file1'); +'asdf'.to('tmp/tree/file2'); +fs.chmodSync('tmp/tree/file1', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree'); +assert.equal(fs.existsSync('tmp/tree'), false); + +// removal of a sub-tree containing read-only and hidden files - rm('dir/*') +shell.mkdir('-p', 'tmp/tree3'); +shell.mkdir('-p', 'tmp/tree3/subtree'); +shell.mkdir('-p', 'tmp/tree3/.hidden'); +'asdf'.to('tmp/tree3/subtree/file'); +'asdf'.to('tmp/tree3/.hidden/file'); +'asdf'.to('tmp/tree3/file'); +fs.chmodSync('tmp/tree3/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree3/subtree/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree3/.hidden/file', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree3/*', 'tmp/tree3/.*'); // erase dir contents +assert.equal(shell.ls('tmp/tree3').length, 0); + +// removal of a sub-tree containing read-only and hidden files - rm('dir') +shell.mkdir('-p', 'tmp/tree4'); +shell.mkdir('-p', 'tmp/tree4/subtree'); +shell.mkdir('-p', 'tmp/tree4/.hidden'); +'asdf'.to('tmp/tree4/subtree/file'); +'asdf'.to('tmp/tree4/.hidden/file'); +'asdf'.to('tmp/tree4/file'); +fs.chmodSync('tmp/tree4/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree4/subtree/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree4/.hidden/file', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree4'); // erase dir contents +assert.equal(fs.existsSync('tmp/tree4'), false); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/sed.js b/enyo/tools/node_modules/shelljs/test/sed.js new file mode 100644 index 0000000..d919cb4 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/sed.js @@ -0,0 +1,58 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.sed(); +assert.ok(shell.error()); + +shell.sed(/asdf/g); // too few args +assert.ok(shell.error()); + +shell.sed(/asdf/g, 'nada'); // too few args +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.sed(/asdf/g, 'nada', '/asdfasdf'); // no such file +assert.ok(shell.error()); + +// +// Valids +// + +shell.cp('-f', 'resources/file1', 'tmp/file1') +var result = shell.sed('test1', 'hello', 'tmp/file1'); // search string +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); + +var result = shell.sed(/test1/, 'hello', 'tmp/file1'); // search regex +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); + +var result = shell.sed(/test1/, 1234, 'tmp/file1'); // numeric replacement +assert.equal(shell.error(), null); +assert.equal(result, '1234'); + +var result = shell.sed('-i', /test1/, 'hello', 'tmp/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); +assert.equal(shell.cat('tmp/file1'), 'hello'); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/silent.js b/enyo/tools/node_modules/shelljs/test/silent.js new file mode 100644 index 0000000..7da94ab --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/silent.js @@ -0,0 +1,26 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// +// Valids +// + +assert.equal(shell.silent(), false); // default + +shell.silent(true); +assert.equal(shell.silent(), true); + +shell.silent(false); +assert.equal(shell.silent(), false); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/tempdir.js b/enyo/tools/node_modules/shelljs/test/tempdir.js new file mode 100644 index 0000000..63448da --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/tempdir.js @@ -0,0 +1,27 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Valids +// + +var tmp = shell.tempdir(); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync(tmp), true); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/test.js b/enyo/tools/node_modules/shelljs/test/test.js new file mode 100644 index 0000000..f074c8a --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/test.js @@ -0,0 +1,83 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +var result = shell.test(); // no expression given +assert.ok(shell.error()); + +var result = shell.test('asdf'); // bad expression +assert.ok(shell.error()); + +var result = shell.test('f', 'resources/file1'); // bad expression +assert.ok(shell.error()); + +var result = shell.test('-f'); // no file +assert.ok(shell.error()); + +// +// Valids +// + +//exists +var result = shell.test('-e', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-e', 'resources/404'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//directory +var result = shell.test('-d', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-f', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-L', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//file +var result = shell.test('-d', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-f', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//link +var result = shell.test('-d', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-f', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/to.js b/enyo/tools/node_modules/shelljs/test/to.js new file mode 100644 index 0000000..4ce9893 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/to.js @@ -0,0 +1,39 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +'hello world'.to(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +'hello world'.to('/asdfasdf/file'); +assert.ok(shell.error()); + +// +// Valids +// + +'hello world'.to('tmp/to1'); +var result = shell.cat('tmp/to1'); +assert.equal(shell.error(), null); +assert.equal(result, 'hello world'); + +shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/which.js b/enyo/tools/node_modules/shelljs/test/which.js new file mode 100644 index 0000000..b733cb6 --- /dev/null +++ b/enyo/tools/node_modules/shelljs/test/which.js @@ -0,0 +1,38 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.silent(true); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp') + +// +// Invalids +// + +shell.which(); +assert.ok(shell.error()); + +var result = shell.which('asdfasdfasdfasdfasdf'); // what are the odds... +assert.equal(shell.error(), null); +assert.equal(result, null); + +// +// Valids +// + +var result = shell.which('node'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync(result), true); + +shell.exit(123); diff --git a/enyo/tools/test/ajax/index.html b/enyo/tools/test/ajax/index.html new file mode 100644 index 0000000..8020cd9 --- /dev/null +++ b/enyo/tools/test/ajax/index.html @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/enyo/tools/test/ajax/package.js b/enyo/tools/test/ajax/package.js new file mode 100644 index 0000000..1dde9a3 --- /dev/null +++ b/enyo/tools/test/ajax/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "$lib/extra/test" +); diff --git a/enyo/tools/test/ajax/php/redball.jpg b/enyo/tools/test/ajax/php/redball.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c836adca6be5af12c1002b24d432067d3e4cce35 GIT binary patch literal 396 zcmex=hUwp4U!^w!2dQ|0V!zR8`IZ literal 0 HcmV?d00001 diff --git a/enyo/tools/test/ajax/php/test1.php b/enyo/tools/test/ajax/php/test1.php new file mode 100644 index 0000000..ab54aa8 --- /dev/null +++ b/enyo/tools/test/ajax/php/test1.php @@ -0,0 +1,18 @@ +' . "\n"; + echo "hello"; +} elseif ($format == 'jsonp') { + header('Content-Type: text/javascript'); + echo "$callback("; + echo json_encode(array('response' => 'hello', 'utf8' => 'Ви́хри')); + echo ');'; +} else { + echo json_encode(array('response' => 'hello')); +} +?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test2.php b/enyo/tools/test/ajax/php/test2.php new file mode 100644 index 0000000..3bc83e6 --- /dev/null +++ b/enyo/tools/test/ajax/php/test2.php @@ -0,0 +1,54 @@ + "get"); + echo json_encode($result); +} + +function post() { + $q = @$_POST['query']; + if ($q) { + $result = array('response' => "post.".$q); + } else { + $q = @$_GET['query']; + if ($q) { + $result = array('response' => "query.".$q); + }else{ + $result = array('response' => file_get_contents('php://input')); + } + } + $requested_with = @$_SERVER['HTTP_X_REQUESTED_WITH']; + if ($requested_with == 'XMLHttpRequest') { + $result['isAjax'] = true; + } + echo json_encode($result); +} + +function put() { + $c = @$_SERVER["CONTENT_TYPE"]; + $result = array('status' => "put", 'ctype' => $c); + echo json_encode($result); +} + +function delete() { + $result = array('status' => "delete"); + echo json_encode($result); +} +?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test3.php b/enyo/tools/test/ajax/php/test3.php new file mode 100644 index 0000000..6e8ab20 --- /dev/null +++ b/enyo/tools/test/ajax/php/test3.php @@ -0,0 +1,15 @@ + "get"); + echo json_encode($result); +} diff --git a/enyo/tools/test/ajax/php/test4.php b/enyo/tools/test/ajax/php/test4.php new file mode 100644 index 0000000..0a70096 --- /dev/null +++ b/enyo/tools/test/ajax/php/test4.php @@ -0,0 +1,22 @@ + "post" , 'ctype' => $ctype , 'cacheCtrl' => $cacheCtrl); + echo json_encode($result); + + # useful for test setup... + #foreach ($_SERVER as $name => $value) { + # echo "$name: $value\n"; + #} +} +?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test5.php b/enyo/tools/test/ajax/php/test5.php new file mode 100644 index 0000000..cddb60a --- /dev/null +++ b/enyo/tools/test/ajax/php/test5.php @@ -0,0 +1,20 @@ +header('HTTP/1.1 500: Internal Server Error'); + //header('HTTP/1.1 500 Internal Server Error'); + //http_response_code(500); // php >= 5.4 + header('X-PHP-Response-Code: 500', true, 500); // php >= 4.3 + + // can't use odd charset due to IE exception throwing + //header('Content-Type: text/plain; charset=x-user-unparseable'); + header('Content-Type: text/plain; charset=utf-8'); + + echo "my error description"; + break; + default: + echo "invalid method"; +} +?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test6.php b/enyo/tools/test/ajax/php/test6.php new file mode 100644 index 0000000..8c7b124 --- /dev/null +++ b/enyo/tools/test/ajax/php/test6.php @@ -0,0 +1,31 @@ + "get"); + echo json_encode($result); + + # $attachment_location = $_SERVER["DOCUMENT_ROOT"] . "/file.zip"; + $attachment_location = "redball.jpg"; + if (file_exists($attachment_location)) { + + header($_SERVER["SERVER_PROTOCOL"] . " 200 OK"); + header("Cache-Control: public"); // needed for i.e. + header("Content-Type: image/jpeg"); + header("Content-Transfer-Encoding: Binary"); + header("Content-Length:".filesize($attachment_location)); + header("Content-Disposition: attachment; filename=redball.jpg"); + readfile($attachment_location); + die(); + } else { + die("Error: File not found."); + } +} diff --git a/enyo/tools/test/ajax/tests/AjaxTest.js b/enyo/tools/test/ajax/tests/AjaxTest.js new file mode 100644 index 0000000..3f39596 --- /dev/null +++ b/enyo/tools/test/ajax/tests/AjaxTest.js @@ -0,0 +1,246 @@ +enyo.kind({ + name: "AjaxTest", + kind: enyo.TestSuite, + timeout: 10000, + testContextSuccess: function (){ + var self = this, + context = {testStatus: 'success'}; + return new enyo.Ajax({url: "php/test1.php?format=test"}) + .response(context, function(inSender, inValue) { + if (this.testStatus && this.testStatus === 'success') { + self.finish(""); + } else { + self.finish("response context not correctly bound"); + } + }) + .error(context, function(inSender, inError) { + self.finish("simple request failed"); + }) + .go(); + }, + testContextFailure: function (){ + var self = this, + context = {testStatus: 'success'}; + return new enyo.Ajax({url: "php/nowhere.php"}) + .response(context, function(inSender, inValue) { + self.finish("simple request failed"); + }) + .error(context, function(inSender, inError) { + if (this.testStatus && this.testStatus === 'success') { + self.finish(""); + } else { + self.finish("failure context not correctly bound"); + } + }) + .go(); + }, + _testAjax: function(inProps, inParams, inAssertFn, inAssertErrFn) { + return new enyo.Ajax(inProps) + .response(this, function(inSender, inValue) { + this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue)); + }) + .error(this, function(inSender, inError) { + if (!inAssertErrFn) { + this.finish("bad status: " + inError.toString()); + enyo.error(inError); + enyo.error(inError.stack); + } else { + this.finish(inAssertErrFn.call(null, inError) ? "" : "bad response: " + inError); + } + }) + .go(inParams); + }, + _testResponse: function(inProps, inAssertFn) { + this._testAjax(enyo.mixin({url: "php/test1.php?format=" + inProps.handleAs}, inProps), null, inAssertFn); + }, + testJsonResponse: function() { + this._testResponse({handleAs: "json"}, function(inValue) { + return inValue.response == "hello"; + }); + }, + testTextResponse: function() { + this._testResponse({handleAs: "text"}, function(inValue) { + return inValue == "hello"; + }); + }, + testXmlResponse: function() { + this._testResponse({handleAs: "xml"}, function(inValue) { + var r = inValue.getElementsByTagName("response")[0].childNodes[0].nodeValue; + return r == "hello"; + }); + }, + testSyncTextResponse: function() { + this._testResponse({handleAs: "text", sync: true}, function(inValue) { + return inValue == "hello"; + }); + }, + // try a post with query object + testPostRequestQuery: function() { + this._testAjax({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) { + return inValue.response == "query.enyo"; + }); + }, + testPostRequestQueryWithPayload: function() { + this._testAjax({url: "php/test2.php", method: "POST", postBody:"data"}, {query: "enyo"}, function(inValue) { + return inValue.response == "query.enyo"; + }); + }, + testPostRequestPayload: function() { + this._testAjax({url: "php/test2.php", method: "POST", postBody:"query=enyo"}, null, function(inValue) { + return inValue.response == "post.enyo"; + }); + }, + testPutRequest: function() { + this._testAjax({url: "php/test2.php", method: "PUT"}, null, function(inValue) { + return inValue.status == "put"; + }); + }, + testDeleteRequest: function() { + this._testAjax({url: "php/test2.php", method: "DELETE"}, null, function(inValue) { + return inValue.status == "delete"; + }); + }, + testHeader: function() { + this._testAjax({url: "php/test2.php", method: "POST", headers: {"X-Requested-With": "XMLHttpRequest"}}, {query: "enyo"}, function(inValue) { + return inValue.isAjax; + }); + }, + testPostBody: function() { + this._testAjax({url: "php/test2.php", method: "POST", postBody: "This is a test."}, null, function(inValue) { + return inValue.response == "This is a test."; + }); + }, + testContentType: function() { + var contentType = "text/plain"; + this._testAjax({url: "php/test2.php", method: "PUT", contentType: contentType}, null, function(inValue) { + return (inValue.ctype === contentType); + }); + }, + testCacheControlOn: function() { + // skip test on non-iOS platforms, since Firefox always sends cache-control header causing + // false positive + if (!enyo.platform.ios) { + this.finish(); + return; + } + var contentType = "application/x-www-form-urlencoded"; + this._testAjax({url: "php/test4.php", method: "POST", postBody: "data"}, null, function(inValue) { + if (enyo.platform.ios && enyo.platform.ios >= 6) { + var status = inValue.cacheCtrl && (inValue.cacheCtrl.indexOf('no-cache') === 0); + if (!status) { + enyo.log("Bad Cache-Control: " + inValue.cacheCtrl + " expected: " + "no-cache"); + } + return status; + } else { + return true; + } + }); + }, + testCacheControlOff: function() { + // skip test on non-iOS platforms, since Firefox always sends cache-control header causing + // false positive + if (!enyo.platform.ios) { + this.finish(); + return; + } + var contentType = "application/x-www-form-urlencoded"; + this._testAjax({url: "php/test4.php", method: "POST", postBody: "data", headers: {'cache-control': null} }, null, function(inValue) { + var status = (inValue.cacheCtrl === null); + if (!status) { + enyo.log("Bad Cache-Control: " + inValue.cacheCtrl + " expected: " + undefined); + } + return status; + }); + }, + testContentTypeDefault: function() { + var contentType = "application/x-www-form-urlencoded"; + this._testAjax({url: "php/test4.php", method: "POST", postBody: "data"}, null, function(inValue) { + var status = (inValue.ctype.indexOf(contentType) === 0); + if (!status) { + enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); + } + return status; + }); + }, + testContentTypeFormDataField: function() { + var formData = new enyo.FormData(); + formData.append('token', "data"); + var contentType = "multipart/form-data"; + this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) { + var status = (inValue.ctype.indexOf(contentType) === 0) && + (inValue.ctype.indexOf("boundary=--") > 10); + if (!status) { + enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); + } + return status; + }); + }, + testContentTypeFormDataFile: function() { + var formData = new enyo.FormData(); + var file = new enyo.Blob(["Some Random File Content!", "And some more..."], { + name: "myFile" + }); + formData.append('file', file); + var contentType = "multipart/form-data"; + this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) { + var status = (inValue.ctype.indexOf(contentType) === 0) && + (inValue.ctype.indexOf("boundary=--") > 10); + if (!status) { + enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); + } + return status; + }); + }, + testXhrStatus: function() { + var ajax = this._testAjax({url: "php/test2.php"}, null, function(inValue) { + return ajax.xhr.status == 200; + }); + }, + testXhrFields: function() { + var ajax = this._testAjax({url: "php/test2.php", xhrFields: {withCredentials: true}}, null, function(inValue) { + return ajax.xhr.withCredentials; + }); + }, + // test CORS (Cross-Origin Resource Sharing) by testing against youtube api + testCORS: function() { + this._testAjax({url: "http://query.yahooapis.com/v1/public/yql/jonathan/weather/"}, {q:'select * from weather.forecast where location=94025', format: "json"}, function(inValue) { + return inValue && inValue.query && inValue.query.results && inValue.query.count > 0; + }); + }, + // test CORS failure + testCORSFailure: function() { + new enyo.Ajax({url: "https://dev.virtualearth.net/REST/v1/Locations/47.64054,-122.12934"}) + .response(this, function(inSender, inValue) { + this.finish("CORS failure flagged as success"); + }) + .error(this, function(inSender, inValue) { + this.finish(""); + }) + .go(); + }, + // server is set to respond after 3 seconds, so make sure timeout fires first + testAjaxTimeout: function() { + new enyo.Ajax({url: "php/test3.php", timeout: 500}) + .response(this, function(inSender, inValue) { + this.finish("did not timeout"); + }) + .error(this, function(inSender, inValue) { + // extra timeout is to make sure that timeout fail code cancels XHR + enyo.job("timeouttest", enyo.bind(this, function() {this.finish("");}), 4000); + }) + .go(); + }, + // expected to fail + testErrorResponse: function() { + var req = this._testAjax({url: "php/test5.php"}, null, function(inValue) { + // getting success means server sent wrong response + return false; + }, function(inError) { + return (inError === 500) && + req.xhrResponse && + (req.xhrResponse.status === 500) && + (req.xhrResponse.headers['content-type'] === "text/plain; charset=utf-8") && + (req.xhrResponse.body === "my error description"); + }); + } +}); diff --git a/enyo/tools/test/ajax/tests/JsonpTest.js b/enyo/tools/test/ajax/tests/JsonpTest.js new file mode 100644 index 0000000..eeec061 --- /dev/null +++ b/enyo/tools/test/ajax/tests/JsonpTest.js @@ -0,0 +1,29 @@ +enyo.kind({ + name: "JsonpTest", + kind: enyo.TestSuite, + _testJsonp: function(inProps, inParams, inAssertFn) { + return new enyo.JsonpRequest(inProps) + .response(this, function(inSender, inValue) { + this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue)); + }) + .error(this, function(inSender, inValue) { + this.finish("bad status: " + inValue); + enyo.error(inValue); + }) + .go(inParams); + }, + _testResponse: function(inProps, inAssertFn) { + this._testJsonp(enyo.mixin({url: "php/test1.php?format=jsonp", callbackName: "callback"}, inProps), + null, inAssertFn); + }, + testJsonResponse: function() { + this._testResponse({}, function(inValue) { + return inValue.response == "hello"; + }); + }, + testCharset: function() { + this._testResponse({charset: "utf8"}, function(inValue) { + return inValue.utf8 == "\u0412\u0438\u0301\u0445\u0440\u0438"; + }); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/WebServiceTest.js b/enyo/tools/test/ajax/tests/WebServiceTest.js new file mode 100644 index 0000000..fc1f4ff --- /dev/null +++ b/enyo/tools/test/ajax/tests/WebServiceTest.js @@ -0,0 +1,112 @@ +enyo.kind({ + name: "WebServiceTest", + kind: enyo.TestSuite, + timeout: 10000, + _testWebService: function(inProps, inParams, inAssertFn) { + var ws = this.createComponent({kind: enyo.WebService, onResponse: "_response", onError: "_error", assertFn: inAssertFn}, inProps); + return ws.send(inParams); + }, + _response: function(inSender, inValue) { + this.finish(inSender.assertFn(inValue.data) ? "" : "bad response: " + JSON.stringify(inValue.data)); + }, + _error: function(inSender, inValue) { + this.finish("bad status: " + inValue.data); + }, + _testResponse: function(inProps, inAssertFn) { + this._testWebService(enyo.mixin({url: "php/test1.php?format=" + (inProps.format || inProps.handleAs)}, inProps), null, inAssertFn); + }, + testJsonResponse: function() { + this._testResponse({handleAs: "json"}, + function(inValue) { + return inValue.response == "hello"; + } + ); + }, + testTextResponse: function() { + this._testResponse({handleAs: "text"}, function(inValue) { + return inValue == "hello"; + }); + }, + testXmlResponse: function() { + this._testResponse({handleAs: "xml"}, function(inValue) { + var r = inValue.getElementsByTagName("response")[0].childNodes[0].nodeValue; + return r == "hello"; + }); + }, + testPostRequest: function() { + this._testWebService({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) { + return inValue.response == "query.enyo"; + }); + }, + testPutRequest: function() { + this._testWebService({url: "php/test2.php", method: "PUT"}, null, function(inValue) { + return inValue.status == "put"; + }); + }, + testDeleteRequest: function() { + this._testWebService({url: "php/test2.php", method: "DELETE"}, null, function(inValue) { + return inValue.status == "delete"; + }); + }, + testHeader: function() { + this._testWebService({url: "php/test2.php", method: "POST", headers: {"X-Requested-With": "XMLHttpRequest"}}, {query: "enyo"}, function(inValue) { + return inValue.isAjax; + }); + }, + testPostBody: function() { + this._testWebService({url: "php/test2.php", method: "POST", postBody: "This is a test."}, null, function(inValue) { + return inValue.response == "This is a test."; + }); + }, + testContentType: function() { + var contentType = "text/plain"; + this._testWebService({url: "php/test2.php", method: "PUT", contentType: contentType}, null, function(inValue) { + return inValue.ctype == contentType; + }); + }, + testXhrStatus: function() { + var ajax = this._testWebService({url: "php/test2.php"}, null, function(inValue) { + return ajax.xhr.status == 200; + }); + }, + testXhrFields: function() { + var ajax = this._testWebService({url: "php/test2.php", xhrFields: {withCredentials: true}}, null, function(inValue) { + return ajax.xhr.withCredentials; + }); + }, + // test CORS (Cross-Origin Resource Sharing) by testing against youtube api + testCORS: function() { + this._testWebService({ + url: "http://query.yahooapis.com/v1/public/yql/jonathan/weather/"}, + {q: 'select * from weather.forecast where location=94025', format: "json"}, + function(inValue) { + enyo.log(inValue); + return inValue && inValue.query && inValue.query.results && inValue.query.count > 0; + }); + }, + testJsonp: function() { + this._testResponse({jsonp: true, format: "jsonp"}, function(inValue) { + return inValue.response == "hello"; + }); + }, + /*testCharset: function() { + this._testResponse({charset: "utf8"}, function(inValue) { + return inValue.utf8 == "\u0412\u0438\u0301\u0445\u0440\u0438"; + }); + } + */ + // server is set to respond after 3 seconds, so make sure timeout fires first + _timeoutResponse: function(inSender, inEvent) { + this.finish("did not timeout"); + }, + _timeoutError: function(inSender, inEvent) { + // extra timeout is to make sure that timeout fail code cancels XHR + enyo.job("wstimeouttest", enyo.bind(this, function() {this.finish("");}), 4000); + }, + testTimeout: function() { + var ws = this.createComponent({kind: enyo.WebService, + onResponse: "_timeoutResponse", onError: "_timeoutError"}, + {url: "php/test3.php", timeout: 500}); + ws.send(); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/XhrTest.js b/enyo/tools/test/ajax/tests/XhrTest.js new file mode 100644 index 0000000..6d3ee5f --- /dev/null +++ b/enyo/tools/test/ajax/tests/XhrTest.js @@ -0,0 +1,16 @@ +enyo.kind({ + name: "XhrTest", + kind: enyo.TestSuite, + testXhrSync: function() { + var x = enyo.xhr.request({ + url: "php/test1.php?format=text", + sync: true + }); + if (x.responseText) { + this.finish(""); + } + else { + this.finish("sync XHR didn't return with text"); + } + } +}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/package.js b/enyo/tools/test/ajax/tests/package.js new file mode 100644 index 0000000..a16be51 --- /dev/null +++ b/enyo/tools/test/ajax/tests/package.js @@ -0,0 +1,6 @@ +enyo.depends( + "XhrTest.js", + "AjaxTest.js", + "JsonpTest.js", + "WebServiceTest.js" +); diff --git a/enyo/tools/test/core/index.html b/enyo/tools/test/core/index.html new file mode 100644 index 0000000..929e707 --- /dev/null +++ b/enyo/tools/test/core/index.html @@ -0,0 +1,15 @@ + + + + Enyo Core Tests + + + + + + + + + diff --git a/enyo/tools/test/core/test.css b/enyo/tools/test/core/test.css new file mode 100644 index 0000000..26f0fa7 --- /dev/null +++ b/enyo/tools/test/core/test.css @@ -0,0 +1,33 @@ +.enyo-testcase { + font-family: Helvetica, Arial, sans-serif; + font-size: smaller; +} + +.enyo-testcase-title { + font-weight: bold; + padding: 4px; + color: white; + background-color: #222; + text-align: center; +} + +.enyo-testcase-group { +} + +.enyo-testcase-running, .enyo-testcase-passed, .enyo-testcase-failed { + padding: 4px 4px 4px 36px; + border-bottom: 1px dotted gray; + white-space: pre; +} + +.enyo-testcase-running { + background-color: yellow; +} + +.enyo-testcase-passed { + background-color: #B0FFB0; +} + +.enyo-testcase-failed { + background-color: #FF8080; +} \ No newline at end of file diff --git a/enyo/tools/test/core/test.js b/enyo/tools/test/core/test.js new file mode 100644 index 0000000..b5f7fb8 --- /dev/null +++ b/enyo/tools/test/core/test.js @@ -0,0 +1,303 @@ + +// TestRunner.js + +/* +To add a test case: + 1) Create a subclass of EnyoTestCase + 2) Add file to package.js +*/ +enyo.kind({ + name: "enyo.TestRunner", + kind: enyo.Control, + index: 0, + rendered: function() { + this.inherited(arguments); + this.next(); + }, + next: function() { + var test = enyo.TestSuite.tests[this.index++]; + if (test) { + this.createComponent({name: test.prototype.kindName, kind: enyo.TestReporter, onFinishAll: "next"}).render().runTests(); + } + } +}); + +// TestSuite.js + +/*global enyo, console +*/ +/* +Test Package Wish list: +----------------------- +Collapse success results for a suite, so large swaths of green don't hide the red. +Expandable stack trace & logging for failures, so they can be collapsed by default. +Support for async beforeEach & afterEach +Jasmine style assert mechanism, so we can have fancy english text for failures + e.g., this.assert("spreadsheet total", total).equals(15) yields "Expected spreadsheet total 12 to equal 15" + +*/ + + +/** + To implement a suite of unit tests, create a subkind of enyo.TestSuite. + Any methods in your subkind that begin with 'test' will be invoked as unit tests when the test runner executes. + + When each test is complete, it should call this.finish(). + Pass nothing for success, or something truthy for failure (usually an explanatory message or an exception object). + If you do not call finish(), your test will be failed after a 3-second timeout. + This timeout can be customized for a given test by calling this.resetTimeout(ms). + + + See enyo-support/tests for example framework tests. + +*/ +enyo.kind({ + name: "enyo.TestSuite", + kind: enyo.Component, + events: { + onBegin: "", // sent with test name as each test begins running. + onFinish: "", // sent with result as each test completes. + onFinishAll: "" // sent when all tests are finished. + }, + timeout: 3000, + timeoutMessage: "timed out", + /** @public + Replaces the current test timeout with + May be called by individual tests to reset/lengthen/shorten the test timeout. + Mostly good for unusually long-running tests, but can be used for shortening the timeout duration, or + even for setting different timeouts for successive stages of a test. + */ + resetTimeout: function(timeout) { + this.clearTimer(); + this.timer = window.setTimeout(enyo.bind(this, "timedout"), timeout || this.timeout); + }, + /** @public + Tests can call this.log() to print useful diagnostic information. + The logs are accumulated, and only displayed when the test fails. + Logged objects will be automatically converted to JSON. + */ + log: function(msg) { + this.logMessages = this.logMessages || []; + if (typeof msg !== "string") { + msg = JSON.stringify(msg); + } + this.logMessages.push(msg); + }, + // Subclasses can override this method. + // It will be called before each test executes. + // It can be used to run common setup code. + beforeEach: function() { + }, + // Subclasses can override this method. + // It will be called exactly once as each test finishes, even in failure cases. + // It can be used to reliably execute cleanup code. + afterEach: function() { + }, + // Runs all the tests in the suite. + // This component can operate in a couple of modes... one where it runs all tests, and one where it runs only a single test. + // When running all tests, it allocates a fresh child component for each test, and then uses that to do actually run the test, + // passing along any relevant events to our owner. The reason for this is to eliminate unintentional state sharing between tests, + // and to make sure that lingering test code that calls finish() at a later time does not affect the state of a different test. + runAllTests: function() { + if (this.autoRunNextTest) { + console.error("TestSuite.runAllTests: Already running."); + return; // already running. + } + this.testNames = this.getTestNames(); + this.index = 0; + this.autoRunNextTest = true; + this.next(); + }, + getTestNames: function() { + // NOTE: name no function or property test* before this point unless it's really a test + var names = []; + for (var key in this) { + if (/^test/.test(key)) { + names.push(key); + } + } + return names; + }, + next: function() { + var testName; + if (!this.autoRunNextTest) { + return; + } + testName = this.testNames[this.index++]; + this.current = testName; + if (testName) { + // Allocate a new child component to run the test. + if (this.$[testName]) { + this.$[testName].destroy(); + } + this.createComponent({name: testName, kind:this.kind, onBegin: "childTestBegun", onFinish: "childTestFinished"}); + this.$[testName].runTest(testName); + } else { + this.autoRunNextTest = false; + this.doFinishAll(); + } + }, + // Called on a component running in the "run a single test" mode to run the actual test. + runTest: function(inTestName) { + this.resetTimeout(); + this.doBegin({testName: inTestName}); + try { + // actual test code invoked here + this.beforeEach(); + this[inTestName](); + } catch(x) { + this.finish(x); + } + }, + timedout: function() { + this.finish(this.timeoutMessage); + }, + clearTimer: function() { + window.clearTimeout(this.timer); + }, + // Call finish() to indicate success, or finish("") to indicate failure. + finish: function(inMessage) { + enyo.asyncMethod(this, "reallyFinish", inMessage); + }, + reallyFinish: function(inMessage) { + // If finish has been called before, then we ignore it + // unless we passed previously and now we're failing. + // We will send multiple finish events if we get a success and then a failure -- that counts as a failure. + if (this.results) { + console.warn("Finish called more than once in test "+this.name); + if (!this.results.passed || !inMessage) { + return; + } + } + this.results = { + suite: this.kindName, + name: this.name, + passed: !inMessage, + logs: this.logMessages + }; + if (inMessage) { + if ((typeof inMessage) === "string") { // In message could be a string... + this.results.message = inMessage; + } else if (inMessage.message !== undefined) { // ... or an exception ... + this.results.message = inMessage.message; + this.results.exception = inMessage; + } else { // ... or some other object ... + this.results.message = inMessage.errorText || inMessage.toString(); + this.results.failValue = inMessage; + } + // Except for timeouts, make sure we have an exception so we can get a backtrace. + if (!this.results.exception && inMessage !== this.timeoutMessage) { + try { + throw new Error(inMessage); + } catch(e) { + this.results.exception = e; + } + } + } + this.clearTimer(); + // Execute afterEach method, if we haven't already. + if (this.afterEach) { + try { + this.afterEach(); + } catch(x) { + this.afterEach = null; // so we don't try again when we recurse. + this.finish(x); // we count an afterEach exception as a failure, even if the test result was originally success. + } + this.afterEach = null; // so we don't try again + } + this.doFinish({results: this.results}); // bubble results + }, + childTestBegun: function(inSender) { + // Pass child test begin event up, with the test name. + // This can be used to trigger UI. + this.triggeredNextTest = false; + }, + childTestFinished: function(inSender, inResults) { + // We do not destroy the child component yet, in case it calls finish() again later with a failure... in that case, we still fail it. + if (!this.triggeredNextTest) { + this.triggeredNextTest = true; + enyo.asyncMethod(this, "next"); + } + } + +}); + +enyo.TestSuite.tests = []; + +enyo.TestSuite.subclass = function(ctor, props) { + // make a list of TestSuite subclasses so we can run them automatically + // if one needs to make a TestSuite subclass that isn't actually a TestSuite itself, + // they should assign a truthy 'testBase' property + if (!props.testBase) { + enyo.TestSuite.tests.push(ctor); + } +}; + +// TestReporter.js + +// UI kind responsible for creating test component, running tests, receiving & displaying test results. +enyo.kind({ + name: "enyo.TestReporter", + kind: enyo.Control, + published: { + results: null + }, + events: { + onFinishAll: "" + }, + components: [ + {name: "title", classes: "enyo-testcase-title"}, + {name: "group", classes: "enyo-testcase-group"} + ], + classes: "enyo-testcase", + timeout: 3000, + create: function() { + this.inherited(arguments); + this.$.title.setContent(this.name); + }, + initComponents: function() { + this.inherited(arguments); + this.createComponent({name: "testSuite", kind: this.name, onBegin: "testBegun", onFinish: "updateTestDisplay"}); + }, + runTests: function() { + this.$.testSuite.runAllTests(); + }, + testBegun: function(inSender, inEvent) { + this.$.group.createComponent({name: inEvent.testName, classes: "enyo-testcase-running", content: inEvent.testName + ": running", allowHtml: true}).render(); + }, + formatStackTrace: function(inStack) { + var stack = inStack.split("\n"); + var out = ['']; + for (var i=0, s; s=stack[i]; i++) { + if (s.indexOf(" at Object.do") == 0 || s.indexOf(" at Object.dispatch") == 0 || s.indexOf("TestSuite.js") != -1) { + continue; + } + out.push(s); + } + return out.join("
    "); + }, + updateTestDisplay: function(inSender, inEvent) { + var results = inEvent.results; + var e = results.exception; + var info = this.$.group.$[results.name]; + var content = "" + results.name + ": " + (results.passed ? "PASSED" : results.message); + if (e) { + // If we have an exception include the stack trace or file/line number. + if (e.stack) { + content += this.formatStackTrace(e.stack); + } else if (e.sourceURL && e.line) { + content += "
    " + e.sourceURL + ":" + e.line; + } + // if fail was called with an object, show the JSON. This is likely a service request error or somesuch. + if (results.failValue) { + content += "
    " + enyo.json.stringify(results.failValue).replace(/\\n/g, "
    "); + } + } + // Show logs if we have any. + if (!results.passed && results.logs) { + content += "
    " + results.logs.join("
    "); + } + info.setContent(content); + info.setClasses("enyo-testcase-" + (results.passed ? "passed" : "failed")); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/AjaxTest.js b/enyo/tools/test/core/tests/AjaxTest.js new file mode 100644 index 0000000..9cb43ab --- /dev/null +++ b/enyo/tools/test/core/tests/AjaxTest.js @@ -0,0 +1,53 @@ +enyo.kind({ + name: "AjaxTest", + kind: enyo.TestSuite, + testAjax200: function() { + new enyo.Ajax({url: "index.html", handleAs: "text"}) + .response(this, function(inSender, inValue){ + this.finish(); + }) + .error(this, function(inSender, inValue) { + this.finish("bad status: " + inValue); + }) + .go(); + }, + testAjax404: function() { + new enyo.Ajax({url: "noexist.not"}) + .response(this, function(inSender, inValue){ + this.finish("ajax failed to fail"); + }) + .error(this, function(inSender, inValue) { + this.finish(); + }) + .go(); + }, + testAjaxCustomError: function() { + new enyo.Ajax({url: "appinfo.json"}) + .response(function(inSender, inValue){ + inSender.fail("cuz I said so"); + }) + .error(this, function(inSender, inValue) { + this.finish(); + }) + .go(); + }, + testAjaxSerial: function() { + // if the test finishes before ready, it's a failure + var ready = false; + // + // when 'index' request completes, we are 'ready' + var index = new enyo.Ajax({url: "index.html", handleAs: "text"}); + index.response(function() { + ready = true; + }); + // + // request triggers 'index' request when it completes + new enyo.Ajax({url: "index.html", handleAs: "text"}) + .response(index) + .response(this, function() { + // finish clean if 'ready' + this.finish(ready ? "" : "requests failed to complete in order"); + }) + .go(); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/AsyncTest.js b/enyo/tools/test/core/tests/AsyncTest.js new file mode 100644 index 0000000..ac859d4 --- /dev/null +++ b/enyo/tools/test/core/tests/AsyncTest.js @@ -0,0 +1,44 @@ +enyo.kind({ + name: "AsyncTest", + kind: enyo.TestSuite, + testAsyncExists: function() { + new enyo.Async(); + this.finish(); + }, + testAsyncFail: function() { + var a = new enyo.Async(); + a.response(this, function(inSender, inValue) { + this.finish("error response not passed to success handler"); + }); + a.error(this, function() { + this.finish(); + }); + a.fail("foo"); + }, + testAsyncInnerFail: function() { + new enyo.Async() + .response(function(inSender, inValue) { + inSender.fail("always fail"); + }) + .error(this, function() { + this.finish(); + }) + .respond("foo") + ; + }, + testAsyncInnerFailRecover: function() { + new enyo.Async() + .response(function(inSender, inValue) { + inSender.fail("first response always fails"); + }) + .error(function(inSender) { + inSender.recover(); + return "recovery response"; + }) + .response(this, function(inSender, inValue) { + this.finish(inValue == "recovery response" ? null : "fail"); + }) + .respond("foo") + ; + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentDispatchTest.js b/enyo/tools/test/core/tests/ComponentDispatchTest.js new file mode 100644 index 0000000..4256514 --- /dev/null +++ b/enyo/tools/test/core/tests/ComponentDispatchTest.js @@ -0,0 +1,74 @@ +enyo.kind({ + name: "ComponentDispatchTest", + kind: enyo.TestSuite, + testDispatchEvent2NullArgs: function() { + var test = this; + var c = new enyo.Component({ + handlers: { + onOk: "ok" + }, + ok: function(inSender, inEvent) { + test.finish((inSender != c && "bad inSender") || (arguments.length !== 2 && "bad arguments")); + } + }); + c.dispatchEvent("onOk"); + }, + testDispatchEvent2OneArg: function() { + var test = this; + var c = new enyo.Component({ + handlers: { + onOk: "ok" + }, + ok: function(inSender, inEvent) { + test.finish((inSender != c && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); + } + }); + c.dispatchEvent("onOk", {value: 42}); + }, + testDispatchEvent2Owner: function() { + var test = this; + var c = new enyo.Component({ + components: [{ + name: "child", + onOk: "ok" + }], + ok: function(inSender, inEvent) { + test.finish((inSender != this.$.child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); + } + }); + c.$.child.dispatchEvent("onOk", {value: 42}); + }, + testBubble: function() { + var test = this; + var c = new enyo.Component({ + components: [{ + name: "child" + }], + handlers: { + onOk: "ok" + }, + ok: function(inSender, inEvent) { + test.finish((inSender != c.$.child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); + } + }); + c.$.child.bubble("onOk", {value: 42}); + }, + testDoubleBubble: function() { + var test = this; + var owner = new enyo.Component({ + handlers: { + onOk: "ok" + }, + ok: function(inSender, inEvent) { + test.finish((inSender != child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); + } + }); + var child = new enyo.Component({ + owner: owner + }); + var grandchild = new enyo.Component({ + owner: child + }); + grandchild.bubble("onOk", {value: 42}); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentHandlersTest.js b/enyo/tools/test/core/tests/ComponentHandlersTest.js new file mode 100644 index 0000000..1f4f716 --- /dev/null +++ b/enyo/tools/test/core/tests/ComponentHandlersTest.js @@ -0,0 +1,22 @@ +enyo.kind({ + name: "ComponentHandlersTest", + kind: enyo.TestSuite, + testHandlerUnion: function() { + enyo.kind({ + name: "TestBase", + kind: enyo.Component, + handlers: { + onOk: "ok" + } + }); + enyo.kind({ + name: "TestSub", + kind: TestBase, + handlers: { + onMore: "more" + } + }); + var h = new TestSub({handlers: {onFurther: "foo"}}).handlers; + this.finish((!h.onOk && "bad onOk") || (!h.onMore && "bad onMore") || (!h.onFurther && "bad onFurther")); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentTest.js b/enyo/tools/test/core/tests/ComponentTest.js new file mode 100644 index 0000000..33e6e89 --- /dev/null +++ b/enyo/tools/test/core/tests/ComponentTest.js @@ -0,0 +1,28 @@ +enyo.kind({ + name: "ComponentTest", + kind: enyo.TestSuite, + testNestedComponentUndefinedKind: function() { + var pass = false; + // should throw exception as this is an error + try { + var a = enyo.kind( + { + name: "parentComponent", + components: [ + { + name: "nestedComponent", + kind: undefined + } + ] + } + ); + new a({}); + } catch(e) { + pass = true; + } + if (!pass) { + throw("no exception for explicitly undefined kind in a nested component"); + } + this.finish(); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ControlPropsTest.js b/enyo/tools/test/core/tests/ControlPropsTest.js new file mode 100644 index 0000000..aa6d435 --- /dev/null +++ b/enyo/tools/test/core/tests/ControlPropsTest.js @@ -0,0 +1,32 @@ +enyo.kind({ + name: "ControlPropsTest", + kind: enyo.TestSuite, + testUnionAttributesStylesClasses: function() { + enyo.kind({ + name: "TestBase", + kind: enyo.Control, + attributes: { + a: 1 + }, + style: "a:1", + classes: "a" + }); + enyo.kind({ + name: "TestSub", + kind: TestBase, + attributes: { + b: 1 + }, + style: "b:1", + classes: "b" + }); + var t = new TestSub({attributes: {c: 1}, style: "c:1", classes: "c"}); + this.finish( + (!t.attributes.a && "bad a attr") || (!t.attributes.b && "bad b attr") || (!t.attributes.c && "bad c attr") + || + (!t.domStyles.a && "bad a style") || (!t.domStyles.b && "bad b style") /*|| (!t.domStyles.c && "bad c style")*/ + || + (t.attributes['class'] !== "a b c" && "bad classes, expected [a b c] got [" + t.attributes['class'] + "]") + ); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ControlTest.js b/enyo/tools/test/core/tests/ControlTest.js new file mode 100644 index 0000000..bf96752 --- /dev/null +++ b/enyo/tools/test/core/tests/ControlTest.js @@ -0,0 +1,92 @@ +enyo.kind({ + name: "ControlTest", + kind: enyo.TestSuite, + testAddingComponents: function() { + var K = enyo.kind({ + kind: enyo.Control, + components: [ + { name: "a" }, + { name: "b" }, + { name: "c" } + ] + }); + + // create new div, attach to start of body, delete at end + // needed because we need live DOM with getElementById working + var div = document.createElement("div"); + document.body.appendChild(div); + + var k = new K(); + k.renderInto(div); + + var kn = div.firstChild; + try { + // basic tests of rendered nodes + if (k.hasNode() !== kn) { + throw("control node doesn't match rendering"); + } + if (kn.firstChild !== k.$.a.hasNode()) { + throw("a child not first node"); + } + if (kn.lastChild !== k.$.c.hasNode()) { + throw("c child not last node"); + } + // test deleting c + k.$.c.destroy(); + if (kn.lastChild !== k.$.b.hasNode()) { + throw("b child not last node after deletion"); + } + // add new node to end + var cc = k.createComponent({}); + cc.render(); + if (kn.lastChild !== cc.hasNode()) { + throw("added a child to end, not last node"); + } + // add new node before a (should be at start) + var aa = k.createComponent({}, {addBefore: k.$.a}); + aa.render(); + if (kn.firstChild !== aa.hasNode()) { + throw("added a child using node reference, not first node"); + } + // add another node to start using addBefore: null + var aaa = k.createComponent({}, {addBefore: null}); + aaa.render(); + if (kn.firstChild !== aaa.hasNode()) { + throw("added a child not first node"); + } + } finally { + // clean up after our test + k.destroy(); + document.body.removeChild(div); + } + this.finish(); + }, + testGetBounds: function() { + var K = enyo.kind({ + style: "position: absolute; top: 10px; height: 30px; left: 15px; width: 35px;" + }); + // create new div, attach to start of body, delete at end + // needed because we need live DOM with getElementById working + var div = document.createElement("div"); + document.body.appendChild(div); + + var k = new K(); + var b; + b = k.getBounds(); + if (b.top !== undefined || b.left !== undefined || b.height !== undefined || b.width !== undefined) { + throw("bad bounds, expected all undefined, got " + JSON.stringify(b)); + } + k.renderInto(div); + try { + b = k.getBounds(); + if (b.top !== 10 || b.left !== 15 || b.height !== 30 || b.width !== 35) { + throw("bad bounds, expected {top: 10, left: 15, height: 30, width: 35}, got " + JSON.stringify(b)); + } + } finally { + // clean up after our test + k.destroy(); + document.body.removeChild(div); + } + this.finish(); + } +}); diff --git a/enyo/tools/test/core/tests/DecodePackagePathTest.js b/enyo/tools/test/core/tests/DecodePackagePathTest.js new file mode 100644 index 0000000..ce8e03c --- /dev/null +++ b/enyo/tools/test/core/tests/DecodePackagePathTest.js @@ -0,0 +1,70 @@ +enyo.kind({ + name: "DecodePackagePathTest", + kind: enyo.TestSuite, + assert: function(inParts, inPart, inValue) { + if (inParts[inPart] != inValue) { + this.finish('bad ' + inPart + ', expected "' + inValue + '" got "' + inParts[inPart] + '"'); + return false; + } + return true; + }, + decodeTest: function(inPath, inExpected) { + var parts = enyo.loaderFactory.prototype.decodePackagePath(inPath); + for (var n in inExpected) { + if (!this.assert(parts, n, inExpected[n])) { + return; + } + } + this.finish(); + }, + testDecodeEmpty: function() { + this.decodeTest("", {folder: "", manifest: "package.js", alias: "", target: ""}); + }, + testDecodeFoo: function() { + this.decodeTest("foo", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); + }, + testDecodeFooSlash: function() { + this.decodeTest("foo/", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); + }, + testDecodeFooBackSlash: function() { + this.decodeTest("foo\\", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); + }, + testDecodeFooBarBaz: function() { + this.decodeTest("foo/bar/baz", {folder: "foo/bar/baz/", manifest: "foo/bar/baz/package.js", alias: "foo-bar-baz", target: "foo/bar/baz"}); + }, + testDecodeParentFoo: function() { + this.decodeTest("../foo", {folder: "../foo/", manifest: "../foo/package.js", alias: "foo", target: "../foo"}); + }, + testDecodeFooBarLibBaz: function() { + this.decodeTest("foo/bar/lib/baz", {folder: "foo/bar/lib/baz/", manifest: "foo/bar/lib/baz/package.js", alias: "baz", target: "foo/bar/lib/baz"}); + }, + testDecodeEnyoFoo: function() { + var $enyo = enyo.path.rewrite("$enyo"); + this.decodeTest($enyo + "/foo", {folder: $enyo + "foo/", manifest: $enyo + "foo/package.js", alias: "foo", target: $enyo + "foo"}); + }, + testDecodeAbsEnyoFoo: function() { + var $enyo = enyo.path.rewrite("$enyo") + "../enyo/"; + this.decodeTest($enyo + "foo", {folder: $enyo + "foo/", manifest: $enyo + "foo/package.js", alias: "foo", target: $enyo + "foo"}); + }, + testDecodeSource: function() { + this.decodeTest("source", {folder: "source/", manifest: "source/package.js", alias: "", target: ""}); + }, + testDecodeFooBarSource: function() { + this.decodeTest("foo/bar/source", {folder: "foo/bar/source/", manifest: "foo/bar/source/package.js", alias: "foo-bar", target: "foo/bar"}); + }, + testDecodeFooBarSourceZot: function() { + this.decodeTest("foo/bar/source/zot", {folder: "foo/bar/source/zot/", manifest: "foo/bar/source/zot/package.js", alias: "foo-bar-zot", target: "foo/bar/zot"}); + }, + testDecodeSourceFoo: function() { + this.decodeTest("source/foo", {folder: "source/foo/", manifest: "source/foo/package.js", alias: "foo", target: "foo"}); + }, + testLocalPackage: function() { + this.decodeTest("package.js", {folder: "", manifest: "package.js", alias: "", target: ""}); + }, + testFooPackage: function() { + this.decodeTest("foo/package.js", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); + }, + testRemote: function() { + this.decodeTest("http://flarn.com/lib/foo", {folder: "http://flarn.com/lib/foo/", manifest: "http://flarn.com/lib/foo/package.js", alias: "foo", target: "http://flarn.com/lib/foo"}); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/JsonTest.js b/enyo/tools/test/core/tests/JsonTest.js new file mode 100644 index 0000000..64a23f9 --- /dev/null +++ b/enyo/tools/test/core/tests/JsonTest.js @@ -0,0 +1,36 @@ +enyo.kind({ + name: "JSONTest", + kind: enyo.TestSuite, + testJsonStringifyExists: function() { + enyo.json.stringify(); + this.finish(); + }, + testJsonParseExists: function() { + enyo.json.parse(); + this.finish(); + }, + testJsonParseSimple: function() { + var obj = enyo.json.parse('{"foo":"bar"}'), err; + if (!obj.foo || obj.foo !== "bar") { + err = "JSON string did not parse correctly"; + } + this.finish(err); + }, + testJsonParseReviver: function() { + var dates = '{"hired":"2012-01-01T12:00:00Z","fired":"2012-01-02T12:00:00Z"}', + parsed = enyo.json.parse(dates, function(key, value) { + var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if ( a ) { + return new Date( + Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]) + ); + } + return value; + }), + err; + if (!(parsed.hired instanceof Date)) { + err = "JSON string did not parse and revive correctly"; + } + this.finish(err); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/KindTest.js b/enyo/tools/test/core/tests/KindTest.js new file mode 100644 index 0000000..266c760 --- /dev/null +++ b/enyo/tools/test/core/tests/KindTest.js @@ -0,0 +1,41 @@ +enyo.kind({ + name: "KindTest", + kind: enyo.TestSuite, + testNamespace: function() { + enyo.kind({name: "custom.Namespace"}); + Boolean(custom.Namespace); // throws an exception if namespace is undefined (Boolean() is just for lint) + this.finish(); + }, + testNullKind: function() { + // should succeed as this is allowed + var K = enyo.kind({kind: null}); + var i = new K({}); + this.finish(); + }, + testUndefinedKind: function() { + // should throw exception as this is an error + var pass = false; + try { + enyo.kind({kind: undefined}); + } catch(e) { + pass = true; + } + if (!pass) { + throw("no exception for explicitly undefined kind"); + } + this.finish(); + }, + testBadStringKind: function() { + // should throw exception as this is an error + var pass = false; + try { + enyo.kind({kind: "FooBarBaz"}); + } catch(e) { + pass = true; + } + if (!pass) { + throw("no exception for misnamed kind"); + } + this.finish(); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/LoaderTest.js b/enyo/tools/test/core/tests/LoaderTest.js new file mode 100644 index 0000000..9f2b7f7 --- /dev/null +++ b/enyo/tools/test/core/tests/LoaderTest.js @@ -0,0 +1,28 @@ +enyo.kind({ + name: "LoaderTest", + kind: enyo.TestSuite, + testSingleLoad: function() { + enyo.load("tests/loader1.js", enyo.bind(this, + function() { + if (window.LOADER_TEST === "loader1") { + this.finish(); + } + else { + this.finish("callback called before load complete"); + } + } + )); + }, + testMultipleLoad: function() { + enyo.load(["tests/loader2a.js", "tests/loader2b.js"], + enyo.bind(this, function() { + if (window.LOADER_TEST === "loader2b") { + this.finish(); + } + else { + this.finish("callback called before load complete"); + } + } + )); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/PathResolverTest.js b/enyo/tools/test/core/tests/PathResolverTest.js new file mode 100644 index 0000000..d98676b --- /dev/null +++ b/enyo/tools/test/core/tests/PathResolverTest.js @@ -0,0 +1,57 @@ +enyo.kind({ + name: "PathResolverTest", + kind: enyo.TestSuite, + rewriteTest: function(inResolver, inPath, inExpected) { + var pf= enyo.loader.packageFolder; + enyo.loader.packageFolder = "./source/"; + + var result = enyo.loader.getPathPrefix(inPath) + inResolver.rewrite(inPath); + + if (result === inExpected) { + this.finish(); + } else { + this.finish("Expected: '" + inExpected + "' Got: '" + result + "'"); + } + + enyo.loader.packageFolder = pf; + }, + testNormalPath: function() { + var resolver = new enyo.pathResolverFactory(); + this.rewriteTest(resolver, "my/folder", "./source/my/folder"); + }, + testLeadingSlashPath: function() { + var resolver = new enyo.pathResolverFactory(); + this.rewriteTest(resolver, "/my/folder", "/my/folder"); + }, + testRewriteHttps: function() { + var resolver = new enyo.pathResolverFactory(); + this.rewriteTest(resolver, "https://my.server/file.js", "https://my.server/file.js"); + }, + testRewriteHttpMixedCase: function() { + var resolver = new enyo.pathResolverFactory(); + this.rewriteTest(resolver, "hTtP://my.server/file.js", "hTtP://my.server/file.js"); + }, + testRewriteUnknown: function() { + var resolver = new enyo.pathResolverFactory(); + this.rewriteTest(resolver, "$enyo/package.js", "package.js"); + }, + testRewriteEnyo: function() { + var resolver = new enyo.pathResolverFactory(); + resolver.addPaths({enyo: "my-enyo-dir", lib: "$enyo/../lib"}); + this.rewriteTest(resolver, "$enyo/package.js", "my-enyo-dir/package.js"); + }, + testRewriteOnyx: function() { + var resolver = new enyo.pathResolverFactory(); + resolver.addPaths({enyo: "my-enyo-dir", lib: "$enyo/../lib"}); + this.rewriteTest(resolver, "$lib/onyx", "my-enyo-dir/../lib/onyx"); + }, + testRewriteEnyoPath: function() { + var input = "$lib/onyx"; + var result = enyo.path.rewrite(input); + if (result !== "onyx" && result != input) { + this.finish(); + } else { + this.finish("Got: '" + result + "'"); + } + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ViewportPositioningTest.js b/enyo/tools/test/core/tests/ViewportPositioningTest.js new file mode 100644 index 0000000..96aa501 --- /dev/null +++ b/enyo/tools/test/core/tests/ViewportPositioningTest.js @@ -0,0 +1,104 @@ +enyo.kind({ + name: "ViewportPositioningTest", + kind: enyo.TestSuite, + + testMeasuringViewportCoordinates: function() { + var K = enyo.kind({ + kind: enyo.Control, + style: "position: absolute; top: 10px; left: 10px; width: 10px; height: 10px;" + }); + + // Similar to ControlTest, create a testing div to test DOM information with (delete at end) + var div = document.createElement("div"); + document.body.appendChild(div); + // Apply fixed positioning so that we know where things should be relative to the viewport + div.style.position = 'fixed'; + div.style.top = '0px'; + div.style.left = '0px'; + div.style.width = '100%'; + div.style.height = '100%'; + div.style.boxSizing = 'border-box'; + + var k = new K(); + k.renderInto(div); + + var p = enyo.dom.calcNodePosition(k.hasNode()), + // Bottom and right require calculating viewport size + fromBottom = (document.body.parentNode.offsetHeight > enyo.dom.getWindowHeight() ? enyo.dom.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight) - 20, + fromRight = (document.body.parentNode.offsetWidth > enyo.dom.getWindowWidth() ? enyo.dom.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth) - 20; + if (p.top !== 10) { + this.log('top failed with value: ' + p.top + ' (should be 10)'); + } + if (p.left !== 10) { + this.log('left failed with value: ' + p.left + ' (should be 10)'); + } + if (p.bottom !== fromBottom) { + this.log('bottom failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); + } + if (p.right !== fromRight) { + this.log('right failed with value: ' + p.right + ' (should be ' + fromRight + ')'); + } + if (p.width !== 10) { + this.log('width failed with value: ' + p.width + ' (should be 10)'); + } + if (p.height !== 10) { + this.log('height failed with value: ' + p.height + ' (should be 10)'); + } + + // Now test measuring the element when a parent has a border + div.style.border = "1px solid transparent"; + k.hasNode().style.border = "1px solid transparent"; + p = enyo.dom.calcNodePosition(k.hasNode()), + // We don't count the right border on the element itself because that is taken into account automatically by the element's width measurement + fromBottom -= 3, + fromRight -= 3; + if (p.top !== 11) { + this.log('top with border failed with value: ' + p.top + ' (should be 11)'); + } + if (p.left !== 11) { + this.log('left with border failed with value: ' + p.left + ' (should be 11)'); + } + if (p.bottom !== fromBottom) { + this.log('bottom with border failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); + } + if (p.right !== fromRight) { + this.log('right with border failed with value: ' + p.right + ' (should be ' + fromRight + ')'); + } + if (p.width !== 12) { + this.log('width with border failed with value: ' + p.width + ' (should be 12)'); + } + if (p.height !== 12) { + this.log('height with border failed with value: ' + p.height + ' (should be 12)'); + } + + // And finally, test positioning relative to another node + p = enyo.dom.calcNodePosition(k.hasNode(), div), + // Reset to div size - node height + fromBottom = div.offsetHeight - 22, + fromRight = div.offsetWidth - 22; + if (p.top !== 10) { + this.log('top relative to div failed with value: ' + p.top + ' (should be 10)'); + } + if (p.left !== 10) { + this.log('left relative to div failed with value: ' + p.left + ' (should be 10)'); + } + if (p.bottom !== fromBottom) { + this.log('bottom relative to div failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); + } + if (p.right !== fromRight) { + this.log('right relative to div failed with value: ' + p.right + ' (should be ' + fromRight + ')'); + } + if (p.width !== 12) { + this.log('width relative to div failed with value: ' + p.width + ' (should be 12)'); + } + if (p.height !== 12) { + this.log('height relative to div failed with value: ' + p.height + ' (should be 12)'); + } + + // Clean up + k.destroy(); + document.body.removeChild(div); + + this.finish(this.logMessages && this.logMessages.length ? 'Following measurements failed:' : ''); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/langTest.js b/enyo/tools/test/core/tests/langTest.js new file mode 100644 index 0000000..ab7dde3 --- /dev/null +++ b/enyo/tools/test/core/tests/langTest.js @@ -0,0 +1,54 @@ +enyo.kind({ + name: "langTest", + kind: enyo.TestSuite, + testCallee: function() { + var err = ""; + var fn = function() { + err = (arguments.callee.nom !== 'fn'); + }; + fn.nom = "fn"; + fn(); + this.finish(err); + }, + testClass: function() { + enyo.kind({ + name: "AClass" + }); + var obj = new AClass(); + var err = (typeof AClass !== 'function'); + this.finish(err); + }, + testisString: function() { + + // Create alternate window context to write vars from + var iframe = document.createElement("iframe"), + iframeDoc, err; + + document.body.appendChild(iframe); + iframeDoc = iframe.contentDocument || iframe.contentWindow.document; + iframeDoc.write(""); + iframeDoc.close(); + + if (!enyo.isString("string")) { + err = "enyo.isString() cannot determine strings correctly"; + } + // This will fail: + // - instanceof from another context + // - typeof (b/c it is a string instance) + // https://github.com/enyojs/enyo/issues/2 + if (!enyo.isString(iString)) { + err = "enyo.isString() cannot determine strings written from other window contexts correctly"; + } + + document.body.removeChild(iframe); + this.finish(err); + }, + testindexOfRegular: function() { + var index = enyo.indexOf("foo", [null, null, null, null,"foo"]); + this.finish(index !== 4 ? "Incorrect index" : false); + }, + testindexOfFromIndex: function() { + var index = enyo.indexOf("foo", [null, null, null, null,"foo"], 10); + this.finish(index !== -1 ? "if fromIndex is greater then array length, should return -1" : false); + } +}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader1.js b/enyo/tools/test/core/tests/loader1.js new file mode 100644 index 0000000..1ce75aa --- /dev/null +++ b/enyo/tools/test/core/tests/loader1.js @@ -0,0 +1 @@ +window.LOADER_TEST = "loader1"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader2a.js b/enyo/tools/test/core/tests/loader2a.js new file mode 100644 index 0000000..f94de37 --- /dev/null +++ b/enyo/tools/test/core/tests/loader2a.js @@ -0,0 +1 @@ +window.LOADER_TEST = "loader2a"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader2b.js b/enyo/tools/test/core/tests/loader2b.js new file mode 100644 index 0000000..c0f0391 --- /dev/null +++ b/enyo/tools/test/core/tests/loader2b.js @@ -0,0 +1 @@ +window.LOADER_TEST = "loader2b"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/package.js b/enyo/tools/test/core/tests/package.js new file mode 100644 index 0000000..522b3aa --- /dev/null +++ b/enyo/tools/test/core/tests/package.js @@ -0,0 +1,16 @@ +enyo.depends( + "langTest.js", + //"LoaderTest.js", + "KindTest.js", + "JsonTest.js", + "AsyncTest.js", + "AjaxTest.js", + "ComponentTest.js", + "ComponentDispatchTest.js", + "ComponentHandlersTest.js", + "ControlTest.js", + "ControlPropsTest.js", + "DecodePackagePathTest.js", + "PathResolverTest.js", + "ViewportPositioningTest.js" +); diff --git a/gallery_images/Saramean.scheduler.jpg b/gallery_images/Saramean.scheduler.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfdd6915fe222d32cc9e147f47ec6c120e979a44 GIT binary patch literal 37999 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 BX}tgd literal 0 HcmV?d00001 diff --git a/index.html b/index.html index b48f515..5b07218 100644 --- a/index.html +++ b/index.html @@ -1,113 +1,24 @@ - - Enyo Community Gallery - - - - - - - - - - + + + Scheduler + + + + + + + + + + + + + + + + diff --git a/lib/layout/CONTRIBUTING md b/lib/layout/CONTRIBUTING md new file mode 100644 index 0000000..cbc43fc --- /dev/null +++ b/lib/layout/CONTRIBUTING md @@ -0,0 +1,10 @@ +# Contributions + +Contributions are welcome for Enyo and its associated libraries including onyx and layout. + +Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details +on our contribution policy and guidelines for use of the Enyo-DCO-1.0-Signed-off-by +line in your commits and pull requests. + +If you're interested in introducing new kinds, you might also consider hosting your own repo +and contributing to the [Enyo community gallery](http://enyojs.com/gallery). \ No newline at end of file diff --git a/lib/layout/README.md b/lib/layout/README.md new file mode 100644 index 0000000..43ce1f9 --- /dev/null +++ b/lib/layout/README.md @@ -0,0 +1,71 @@ +### Looking for the issue tracker? +It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). + +--- + +This is a layout library for Enyo 2. This library provides a collection of +layout functionality + +## List + +The list package provides a `List` control that displays a scrolling list of +rows. It's suitable for displaying very large lists and is optimized such that +only a small portion of the list is rendered at a given time. + +Check out the List samples in the Layout section of the +[Enyo Sampler](http://enyojs.com/sampler/) to see the control in action. For +more information, see the [List documentation](https://github.com/enyojs/enyo/wiki/Lists) +in the Enyo Developer Guide. + +## Fittable + +The fittable package helps you create layouts that expand to fit available +space--a common need for apps, but one that has historically been difficult +to meet using Web technologies. + +The `FittableColumns` and `FittableRows` controls let you define views whose +children are arranged either horizontally or vertically. Within a given view, +you can designate one child to expand and contract to fit the available space, +while its siblings retain their natural or explicitly-specified sizes. Fittable +views may be nested as needed. + +If you're thinking that this sounds a lot like a limited version of the CSS +Flexible Box Model, you're right. Our main objective was to provide a layout +model with capabilities similar to Flex Box, but with greater browser +compatibility. We also wanted to impose as few limitations as possible on the +CSS styling of child components, and to use JavaScript sparingly (we use it to +calculate the height of fittable elements, but otherwise leave the layout work +to the browser). + +As much as we like them, we want to emphasize that you should only use +`FittableColumns` and `FittableRows` when you need views to expand and +contract to fit available space. If you simply want to arrange elements +horizontally or vertically, you're better off employing standard Web layout +techniques. + +Check out the +[Fittable sample](http://enyojs.com/samples/fittable/app-layouts.html) to +see `FittableColumns` and `FittableRows` in action. + +## Panels + +The `enyo.Panels` kind is designed to satisfy a variety of common use cases +for application layout. Using `enyo.Panels`, controls may be arranged as +(among other things) a carousel, a set of collapsing panels, a card stack +that fades between panels, or a grid. + +For more information, see the [Panels documentation](https://github.com/enyojs/enyo/wiki/Panels) +on the Enyo wiki. + +## Slidable + +Slideable is a control that can be dragged either left-to-right or up-and-down +between a minimum and a maximum value. When released from dragging, a Slideable +will animate to its minimum or maximum position based on the direction dragged. + +## Tree + +Tree is a control showing a vertical list of labels with nesting and collapsing +of hierarchy levels. There's a simple example in the +[Enyo Sampler](http://enyojs.com/sampler/) showing the control in use as a +directory and file tree. \ No newline at end of file diff --git a/lib/layout/deploy.bat b/lib/layout/deploy.bat new file mode 100644 index 0000000..e69de29 diff --git a/lib/layout/deploy.sh b/lib/layout/deploy.sh new file mode 100644 index 0000000..e69de29 diff --git a/lib/layout/design.js b/lib/layout/design.js new file mode 100644 index 0000000..7016fa3 --- /dev/null +++ b/lib/layout/design.js @@ -0,0 +1,155 @@ +/** + Descriptions to make layout kinds available in Ares. +*/ +Palette.model.push( + {name: "fittable", items: [ + {name: "FittableRows", description: "Vertical stacked layout", + inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ + {style: "background-color: lightblue; border: 1px dotted blue; height: 15px;"}, + {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, + {style: "background-color: lightblue; border: 1px dotted blue; height: 15px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "FittableRows"} + }, + {name: "FittableColumns", description: "Horizontal stacked layout", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightblue; border: 1px dotted blue; width: 20px;"}, + {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, + {style: "background-color: lightblue; border: 1px dotted blue; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "FittableColumns"} + } + ]}, + {name: "imageview", items: [ + {name: "ImageCarousel", description: "A carousel of images", + inline: {}, + config: {content: "$name", isContainer: true, kind: "ImageCarousel"} + }, + {name: "ImageView", description: "A scalable Image View", + inline: {}, + config: {content: "$name", isContainer: true, kind: "ImageView"} + }, + {name: "ImageViewPin", description: "An unscaled item inside an ImageView", + inline: {}, + config: {content: "$name", isContainer: true, kind: "ImageViewPin"} + }, + ]}, + {name: "List", items: [ + {name: "AroundList", description: "List with elements above the list", + inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} + ]}, + config: {content: "$name", isContainer: false, kind: "AroundList", onSetupItem: "", count: 0} + }, + {name: "List", description: "Infinite scrolling list", + inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} + ]}, + config: {content: "$name", isContainer: false, kind: "List", onSetupItem: "", count: 0} + }, + {name: "PulldownList", description: "List with pull-to-refresh", + inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, + {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} + ]}, + config: {content: "$name", isContainer: false, kind: "PulldownList", onSetupItem: "", count: 0} + } + ]}, + {name: "Panels", items: [ + {name: "CardArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CardArranger"} + }, + {name: "CardSlideInArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CardSlideInArranger"} + }, + {name: "CarouselArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CarouselArranger"} + }, + {name: "CollapsingArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CollapsingArranger", components: [ + {content: "Placeholder"} + ]} + }, + {name: "DockRightArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "DockRightArranger"} + }, + {name: "GridArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "GridArranger"} + }, + {name: "LeftRightArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "LeftRightArranger"} + }, + {name: "UpDownArranger", description: "Selectable sub-view", + inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} + ]}, + config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "UpDownArranger"} + }, + ]}, + {name: "Slideable", items: [ + {name: "Slideable", description: "Slideable sub-view", + inline: {kind: "FittableColumns", style: "height: 40px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightblue; border: 1px dotted blue;", fit: true} + ]}, + config: {content: "$name", isContainer: true, kind: "Slideable"} + } + ]}, + {name: "Tree", items: [ + {name: "Node", description: "A tree node", + inline: {kind: "FittableColumns", style: "height: 40px; position: relative;", padding: 4, components: [ + {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, + {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, + ]}, + config: {content: "$name", isContainer: true, kind: "Node"} + } + ]} +); \ No newline at end of file diff --git a/lib/layout/fittable/package.js b/lib/layout/fittable/package.js new file mode 100644 index 0000000..3fae95b --- /dev/null +++ b/lib/layout/fittable/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "source" +); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout1.html b/lib/layout/fittable/samples/FittableAppLayout1.html new file mode 100644 index 0000000..173e15f --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout1.html @@ -0,0 +1,22 @@ + + + + + Fittable App Layout 1 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout1.js b/lib/layout/fittable/samples/FittableAppLayout1.js new file mode 100644 index 0000000..21b9672 --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout1.js @@ -0,0 +1,21 @@ +enyo.kind({ + name: "enyo.sample.FittableAppLayout1", + kind: "FittableRows", + classes: "enyo-fit", + components: [ + {kind: "onyx.Toolbar", components: [ + {content: "Header"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input"} + ]} + ]}, + {kind: "FittableColumns", fit: true, components: [ + {style: "width: 30%;"}, + {kind: "FittableRows", fit: true, classes: "fittable-sample-shadow", components: [ + {classes: "fittable-sample-shadow2", style: "height: 30%; position: relative; z-index: 1;"}, + {fit: true, classes: "fittable-sample-fitting-color"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout2.html b/lib/layout/fittable/samples/FittableAppLayout2.html new file mode 100644 index 0000000..cb9b652 --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout2.html @@ -0,0 +1,22 @@ + + + + + Fittable App Layout 2 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout2.js b/lib/layout/fittable/samples/FittableAppLayout2.js new file mode 100644 index 0000000..14a9f3a --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout2.js @@ -0,0 +1,25 @@ +enyo.kind({ + name: "enyo.sample.FittableAppLayout2", + kind: "FittableColumns", + classes: "enyo-fit", + components: [ + {kind: "FittableRows", style: "width: 20%;", components: [ + {fit: true}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "1"} + ]} + ]}, + {kind: "FittableRows", style: "width: 20%;", classes: "fittable-sample-shadow", components: [ + {fit: true, style: ""}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "2"} + ]} + ]}, + {kind: "FittableRows", fit: true, classes: "fittable-sample-shadow", components: [ + {fit: true, classes: "fittable-sample-fitting-color"}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "3"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout3.html b/lib/layout/fittable/samples/FittableAppLayout3.html new file mode 100644 index 0000000..593a8f3 --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout3.html @@ -0,0 +1,22 @@ + + + + + Fittable App Layout 3 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout3.js b/lib/layout/fittable/samples/FittableAppLayout3.js new file mode 100644 index 0000000..2d8a0c1 --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout3.js @@ -0,0 +1,20 @@ +enyo.kind({ + name: "enyo.sample.FittableAppLayout3", + kind: "FittableColumns", + classes: "enyo-fit", + components: [ + {kind: "FittableRows", fit: true, components: [ + {fit: true, classes: "fittable-sample-fitting-color"}, + {classes: "fittable-sample-shadow3", style: "height: 30%; position: relative;"}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "1"} + ]} + ]}, + {kind: "FittableRows", classes: "fittable-sample-shadow", style: "width: 30%; position: relative;", components: [ + {fit: true}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "2"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout4.html b/lib/layout/fittable/samples/FittableAppLayout4.html new file mode 100644 index 0000000..3dfc7fa --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout4.html @@ -0,0 +1,22 @@ + + + + + Fittable App Layout 4 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout4.js b/lib/layout/fittable/samples/FittableAppLayout4.js new file mode 100644 index 0000000..5ab1532 --- /dev/null +++ b/lib/layout/fittable/samples/FittableAppLayout4.js @@ -0,0 +1,21 @@ +enyo.kind({ + name: "enyo.sample.FittableAppLayout4", + kind: "FittableColumns", + classes: "enyo-fit", + components: [ + {kind: "FittableRows", classes: "fittable-sample-shadow4", style: "width: 30%; position: relative; z-index: 1;", components: [ + {style: "height: 20%;"}, + {style: "height: 20%;"}, + {fit: true}, + {kind: "onyx.Toolbar", style: "height: 57px;", components: [ + {content: "Toolbar"} + ]} + ]}, + {kind: "FittableRows", fit: true, components: [ + {fit: true, classes: "fittable-sample-fitting-color"}, + {kind: "onyx.Toolbar", style: "height: 57px;",components: [ + {kind: "onyx.Button", content: "2"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableDescription.html b/lib/layout/fittable/samples/FittableDescription.html new file mode 100644 index 0000000..5227fcc --- /dev/null +++ b/lib/layout/fittable/samples/FittableDescription.html @@ -0,0 +1,21 @@ + + + + + Fittables Description + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableDescription.js b/lib/layout/fittable/samples/FittableDescription.js new file mode 100644 index 0000000..3b66b6c --- /dev/null +++ b/lib/layout/fittable/samples/FittableDescription.js @@ -0,0 +1,44 @@ +enyo.kind({ + name: "enyo.sample.FittableDescription", + classes: "fittable-sample-box enyo-fit", + style: "padding:10px;", + kind: "Scroller", + components: [ + {tag: "p", allowHtml: true, content: "FittableColumns, no margin on boxes (all divs have some padding). By default, boxes 'stretch' to fit the container (which must have a height)."}, + {kind: "FittableColumns", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box"}, + {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box"}, + {content: "BoxC", classes: "fittable-sample-box"} + ]}, + {tag: "p", allowHtml: true, content: "Boxes with left/right margins. Note: top/bottom margin on column boxes is NOT supported."}, + {kind: "FittableColumns", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr"} + ]}, + {tag: "p", allowHtml: true, content: "With noStretch: true, boxes have natural height."}, + {kind: "FittableColumns", noStretch: true, classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "Fitting BoxB

    with natural height", fit: true, allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr"} + ]}, + {tag: "p", allowHtml: true, content: "FittableRows, no margin on boxes (all divs have some padding)."}, + {kind: "FittableRows", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box"}, + {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box"}, + {content: "BoxC", classes: "fittable-sample-box"} + ]}, + {tag: "p", allowHtml: true, content: "Row boxes may have margin in any dimension.

    NOTE: Row boxes will collapse vertical margins according to css rules. If margin collapse is not desired, then \"enyo-margin-expand\" may be applied. Only in this case, left/right margin on row boxes is NOT supported."}, + {kind: "FittableRows", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"} + ]}, + {tag: "p", allowHtml: true, content: "With noStretch: true, boxes have natural width.

    NOTE: margins will not collapse in this case."}, + {kind: "FittableRows", noStretch: true, classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mtb", components: [ + {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableSample.html b/lib/layout/fittable/samples/FittableSample.html new file mode 100644 index 0000000..ecbe73c --- /dev/null +++ b/lib/layout/fittable/samples/FittableSample.html @@ -0,0 +1,21 @@ + + + + + Fittables Basic Sample + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableSample.js b/lib/layout/fittable/samples/FittableSample.js new file mode 100644 index 0000000..c61fcfa --- /dev/null +++ b/lib/layout/fittable/samples/FittableSample.js @@ -0,0 +1,22 @@ +enyo.kind({ + name: "enyo.sample.FittableSample", + kind: "FittableRows", + classes: "fittable-sample-box enyo-fit", + components: [ + {content: "Foo
    Foo", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb"}, + {content: "Foo
    Foo", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb"}, + {kind: "FittableColumns", fit: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-o", components: [ + {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "Fits!", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, + {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"} + ]}, + {kind: "FittableColumns", content: "Bat", classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ + {content: "Centered", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "4", classes: "fittable-sample-box fittable-sample-mlr"} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableTests.html b/lib/layout/fittable/samples/FittableTests.html new file mode 100644 index 0000000..62a055b --- /dev/null +++ b/lib/layout/fittable/samples/FittableTests.html @@ -0,0 +1,21 @@ + + + + + Fittable Tests + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableTests.js b/lib/layout/fittable/samples/FittableTests.js new file mode 100644 index 0000000..d4f148b --- /dev/null +++ b/lib/layout/fittable/samples/FittableTests.js @@ -0,0 +1,84 @@ +enyo.kind({ + name: "enyo.sample.FittableTests", + classes: "fittable-sample-box enyo-fit", + kind: "Scroller", + components: [ + {classes: "fittable-sample-section", content: "Rows/Columns using a combination of css units and highlighting margin collapse"}, + {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test", style: "height: 400px;", components: [ + {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-bottom: 1em;"}, + {content: "margin-top: 1em (collapsed since sibling shows greater of previous bottom and this top)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-top: 1em;"}, + {content: "FOO
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {kind: "FittableColumns", fit: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-mlr fittable-sample-o", components: [ + {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "2", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, + {content: "3333333", classes: "fittable-sample-box fittable-sample-mlr"} + ]}, + {kind: "FittableColumns", content: "Bat", classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ + {content: "add enyo-center to FittableColumns", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "4", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "5", classes: "fittable-sample-box fittable-sample-mlr"} + ]} + ]}, + {classes: "fittable-sample-section", content: "Rows with enyo-margin-expand to avoid margin-collapse"}, + {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test enyo-margin-expand", style: "height: 250px;", components: [ + {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb", style: "margin-bottom: 1em;"}, + {content: "margin-top: 3em (not collapsed due to enyo-margin-expand on box)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb", style: "margin-top: 3em;"}, + {content: "FOO
    FOO", allowHtml: true, fit: true, classes: "fittable-sample-box fittable-sample-mtb"} + ]}, + {classes: "fittable-sample-section", content: "Tests to ensure fit region can be first, middle, or last"}, + {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A", fit: true}, + {content: "B"}, + {content: "C"} + ]}, + {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A"}, + {content: "B", fit: true}, + {content: "C"} + ]}, + {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A"}, + {content: "B"}, + {content: "C", fit: true} + ]}, + {kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A", fit: true}, + {content: "B"}, + {content: "C"} + ]}, + {kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A"}, + {content: "B", fit: true}, + {content: "C"} + ]}, + {style: "height: 200px;", kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ + {content: "A"}, + {content: "B"}, + {content: "C", fit: true} + ]}, + {classes: "fittable-sample-section", content: "Tests for noStretch: true"}, + {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test", style: "height: 400px;", noStretch: true, components: [ + {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-bottom: 1em;"}, + {content: "margin-top: 2em (not collapsed; stretch false does not collapse due to use of float)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-top: 1em;"}, + {content: "FOO
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, + {kind: "FittableColumns", fit: true, noStretch: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-mlr fittable-sample-o", components: [ + {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "2
    2", allowHtml: true, fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, + {content: "3333333", classes: "fittable-sample-box fittable-sample-mlr"} + ]}, + {kind: "FittableColumns", content: "Bat", noStretch: true, classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ + {content: "add enyo-center to FittableColumns", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "4", classes: "fittable-sample-box fittable-sample-mlr"}, + {content: "5", classes: "fittable-sample-box fittable-sample-mlr"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/package.js b/lib/layout/fittable/samples/package.js new file mode 100644 index 0000000..90784bd --- /dev/null +++ b/lib/layout/fittable/samples/package.js @@ -0,0 +1,9 @@ +enyo.depends( + "sample.css", + "FittableSample.js", + "FittableAppLayout1.js", + "FittableAppLayout2.js", + "FittableAppLayout3.js", + "FittableAppLayout4.js", + "FittableDescription.js" +); \ No newline at end of file diff --git a/lib/layout/fittable/samples/sample.css b/lib/layout/fittable/samples/sample.css new file mode 100644 index 0000000..c537a1e --- /dev/null +++ b/lib/layout/fittable/samples/sample.css @@ -0,0 +1,76 @@ +.fittable-sample-box { + border: 2px solid lightblue; + padding: 4px; +} +.fittable-sample-b { + background-color: #F1FFF1; +} +.fittable-sample-mtb { + margin-top: 3px; + margin-bottom: 3px; +} +.fittable-sample-mlr { + margin-left: 6px; + margin-right: 6px; +} +.fittable-sample-o { + border-color: orange; +} +.fittable-sample-height { + height: 140px; +} + +.fittable-sample-fitting-color { + background: #B7BFC4; +} + +.fittable-sample-shadow { + box-shadow: -6px 0px 6px rgba(0,0,0,0.3); + -moz-box-shadow: -6px 0px 6px rgba(0,0,0,0.3); + -webkit-box-shadow: -6px 0px 6px rgba(0,0,0,0.3); +} + +.fittable-sample-shadow2 { + box-shadow: 6px 6px 6px rgba(0,0,0,0.3); + -moz-box-shadow: 6px 6px 6px rgba(0,0,0,0.3); + -webkit-box-shadow: 6px 6px 6px rgba(0,0,0,0.3); +} + +.fittable-sample-shadow3 { + box-shadow: 0 -6px 6px rgba(0,0,0,0.3); + -moz-box-shadow: 0 -6px 6px rgba(0,0,0,0.3); + -webkit-box-shadow: 0 -6px 6px rgba(0,0,0,0.3); +} + +.fittable-sample-shadow4 { + box-shadow: 6px 0px 6px rgba(0,0,0,0.3); + -moz-box-shadow: 6px 0px 6px rgba(0,0,0,0.3); + -webkit-box-shadow: 6px 0px 6px rgba(0,0,0,0.3); +} + +.fittable-sample-boxable { + margin: 0.5em; + padding: 1em; + border: 0.2em solid beige; +} + +.fittable-sample-boxable > * { + border: 0.1em dotted orange; + padding: 0.5em; +} + +.fittable-sample-test { + border-width: 0.2em; + border-color: red; +} + +.fittable-sample-small-test { + border-width: 0.2em; + border-color: red; + height: 150px; +} + +.fittable-sample-section { + padding: 30px 10px 10px; + font-weight: bold; +} \ No newline at end of file diff --git a/lib/layout/fittable/source/FittableColumns.js b/lib/layout/fittable/source/FittableColumns.js new file mode 100644 index 0000000..ec138cf --- /dev/null +++ b/lib/layout/fittable/source/FittableColumns.js @@ -0,0 +1,19 @@ +/** + _enyo.FittableColumns_ provides a container in which items are laid out in a + set of vertical columns, with most items having natural size, but one + expanding to fill the remaining space. The one that expands is labeled with + the attribute _fit: true_. + + For more information, see the documentation on + [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo + Developer Guide. + +*/ + +enyo.kind({ + name: "enyo.FittableColumns", + layoutKind: "FittableColumnsLayout", + /** By default, items in columns stretch to fit vertically; set to true to + avoid this behavior */ + noStretch: false +}); diff --git a/lib/layout/fittable/source/FittableLayout.css b/lib/layout/fittable/source/FittableLayout.css new file mode 100644 index 0000000..cdc24b8 --- /dev/null +++ b/lib/layout/fittable/source/FittableLayout.css @@ -0,0 +1,69 @@ +.enyo-fittable-rows-layout { + position: relative; +} + +.enyo-fittable-rows-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + /* float when not stretched */ + float: left; + clear: both; +} + +/* non-floating when stretched */ +.enyo-fittable-rows-layout.enyo-stretch > * { + float: none; + clear: none; +} + +/* setting to enforce margin collapsing */ +/* NOTE: rows cannot have margin left/right */ +.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { + float: left; + clear: both; + width: 100%; + /* note: harsh resets */ + margin-left: 0 !important; + margin-right: 0 !important; +} + +.enyo-fittable-columns-layout { + position: relative; + text-align: left; + white-space: nowrap; +} + +.enyo-fittable-columns-layout.enyo-center { + text-align: center; +} + +.enyo-fittable-columns-layout > * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + vertical-align: top; + display: inline-block; + white-space: normal; +} + +.enyo-fittable-columns-layout.enyo-tool-decorator > * { + vertical-align: middle; +} + +/* repair clobbered white-space setting for pre, code */ +.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { + white-space: pre; +} + +.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { + white-space: nowrap; +} + +/* NOTE: columns cannot have margin top/bottom */ +.enyo-fittable-columns-layout.enyo-stretch > * { + height: 100%; + /* note: harsh resets */ + margin-top: 0 !important; + margin-bottom: 0 !important; +} \ No newline at end of file diff --git a/lib/layout/fittable/source/FittableLayout.js b/lib/layout/fittable/source/FittableLayout.js new file mode 100644 index 0000000..412819c --- /dev/null +++ b/lib/layout/fittable/source/FittableLayout.js @@ -0,0 +1,156 @@ +/** + _enyo.FittableLayout_ provides the base positioning and boundary logic for + the fittable layout strategy. The fittable layout strategy is based on + laying out items in either a set of rows or a set of columns, with most of + the items having natural size, but one item expanding to fill the remaining + space. The item that expands is labeled with the attribute _fit: true_. + + The subkinds enyo.FittableColumnsLayout + and enyo.FittableRowsLayout (or + their subkinds) are used for layout rather than _enyo.FittableLayout_ + because they specify properties that the framework expects to be available + when laying items out. + + For more information,see the documentation on + [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.FittableLayout", + kind: "Layout", + //* @protected + calcFitIndex: function() { + for (var i=0, c$=this.container.children, c; (c=c$[i]); i++) { + if (c.fit && c.showing) { + return i; + } + } + }, + getFitControl: function() { + var c$=this.container.children; + var f = c$[this.fitIndex]; + if (!(f && f.fit && f.showing)) { + this.fitIndex = this.calcFitIndex(); + f = c$[this.fitIndex]; + } + return f; + }, + getLastControl: function() { + var c$=this.container.children; + var i = c$.length-1; + var c = c$[i]; + while ((c=c$[i]) && !c.showing) { + i--; + } + return c; + }, + _reflow: function(measure, cMeasure, mAttr, nAttr) { + this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); + var f = this.getFitControl(); + // no sizing if nothing is fit. + if (!f) { + return; + } + // + // determine container size, available space + var s=0, a=0, b=0, p; + var n = this.container.hasNode(); + // calculate available space + if (n) { + // measure 1 + p = enyo.dom.calcPaddingExtents(n); + // measure 2 + s = n[cMeasure] - (p[mAttr] + p[nAttr]); + //enyo.log("overall size", s); + } + // + // calculate space above fitting control + // measure 3 + var fb = f.getBounds(); + // offset - container padding. + a = fb[mAttr] - ((p && p[mAttr]) || 0); + //enyo.log("above", a); + // + // calculate space below fitting control + var l = this.getLastControl(); + if (l) { + // measure 4 + var mb = enyo.dom.getComputedBoxValue(l.hasNode(), "margin", nAttr) || 0; + if (l != f) { + // measure 5 + var lb = l.getBounds(); + // fit offset + size + var bf = fb[mAttr] + fb[measure]; + // last offset + size + ending margin + var bl = lb[mAttr] + lb[measure] + mb; + // space below is bottom of last item - bottom of fit item. + b = bl - bf; + } else { + b = mb; + } + } + + // calculate appropriate size for fit control + var fs = s - (a + b); + //enyo.log(f.id, fs); + // note: must be border-box; + f.applyStyle(measure, fs + "px"); + }, + //* @public + /** + Updates the layout to reflect any changes to contained components or the + layout container. + */ + reflow: function() { + if (this.orient == "h") { + this._reflow("width", "clientWidth", "left", "right"); + } else { + this._reflow("height", "clientHeight", "top", "bottom"); + } + } +}); + +/** + _enyo.FittableColumnsLayout_ provides a container in which items are laid + out in a set of vertical columns, with most of the items having natural + size, but one expanding to fill the remaining space. The one that expands is + labeled with the attribute _fit: true_. + + _enyo.FittableColumnsLayout_ is meant to be used as a value for the + _layoutKind_ property of other kinds. _layoutKind_ provides a way to add + layout behavior in a pluggable fashion while retaining the ability to use a + specific base kind. + + For more information, see the documentation on + [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.FittableColumnsLayout", + kind: "FittableLayout", + orient: "h", + layoutClass: "enyo-fittable-columns-layout" +}); + + +/** + _enyo.FittableRowsLayout_ provides a container in which items are laid out + in a set of horizontal rows, with most of the items having natural size, but + one expanding to fill the remaining space. The one that expands is labeled + with the attribute _fit: true_. + + _enyo.FittableRowsLayout_ is meant to be used as a value for the + _layoutKind_ property of other kinds. _layoutKind_ provides a way to add + layout behavior in a pluggable fashion while retaining the ability to use a + specific base kind. + + For more information, see the documentation on + [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.FittableRowsLayout", + kind: "FittableLayout", + layoutClass: "enyo-fittable-rows-layout", + orient: "v" +}); diff --git a/lib/layout/fittable/source/FittableRows.js b/lib/layout/fittable/source/FittableRows.js new file mode 100644 index 0000000..c196349 --- /dev/null +++ b/lib/layout/fittable/source/FittableRows.js @@ -0,0 +1,17 @@ +/** + _enyo.FittableRows_ provides a container in which items are laid out in a + set of horizontal rows, with most of the items having natural size, but one + expanding to fill the remaining space. The one that expands is labeled with + the attribute _fit: true_. + + For more information, see the documentation on + [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.FittableRows", + layoutKind: "FittableRowsLayout", + /** By default, items in rows stretch to fit horizontally; set to true to + avoid this behavior */ + noStretch: false +}); diff --git a/lib/layout/fittable/source/package.js b/lib/layout/fittable/source/package.js new file mode 100644 index 0000000..74201af --- /dev/null +++ b/lib/layout/fittable/source/package.js @@ -0,0 +1,6 @@ +enyo.depends( + "FittableLayout.css", + "FittableLayout.js", + "FittableRows.js", + "FittableColumns.js" +); \ No newline at end of file diff --git a/lib/layout/imageview/package.js b/lib/layout/imageview/package.js new file mode 100644 index 0000000..1adaff6 --- /dev/null +++ b/lib/layout/imageview/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "source/" +); diff --git a/lib/layout/imageview/samples/ImageCarouselSample.css b/lib/layout/imageview/samples/ImageCarouselSample.css new file mode 100644 index 0000000..7927029 --- /dev/null +++ b/lib/layout/imageview/samples/ImageCarouselSample.css @@ -0,0 +1,8 @@ +.imagecarousel-sample-input { + margin:0px 6px; +} + +.imagecarousel-sample-input input { + text-align:center; + width:30px; +} \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageCarouselSample.html b/lib/layout/imageview/samples/ImageCarouselSample.html new file mode 100644 index 0000000..1a6b27b --- /dev/null +++ b/lib/layout/imageview/samples/ImageCarouselSample.html @@ -0,0 +1,22 @@ + + + + + Image Carousel Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageCarouselSample.js b/lib/layout/imageview/samples/ImageCarouselSample.js new file mode 100644 index 0000000..84ba39d --- /dev/null +++ b/lib/layout/imageview/samples/ImageCarouselSample.js @@ -0,0 +1,74 @@ +enyo.kind({ + name: "enyo.sample.ImageCarouselSample", + kind: "FittableRows", + classes: "enyo-fit", + components: [ + {kind: "onyx.Toolbar", style:"text-align:center;", components: [ + {kind: "onyx.Button", content:"←", allowHtml: true, ontap:"previous"}, + {kind: "onyx.Button", content:"→", allowHtml: true, ontap:"next"}, + {kind: "onyx.InputDecorator", classes: "imagecarousel-sample-input", components: [ + {name: "carouselIndexInput", kind: "onyx.Input", value: "0", onchange: "updateIndex"} + ]} + ]}, + {name:"carousel", kind:"ImageCarousel", fit:true, onload:"load", onZoom:"zoom", onerror:"error", onTransitionStart: "transitionStart", onTransitionFinish: "transitionFinish"} + ], + create: function() { + this.inherited(arguments); + this.urls = [ + "assets/mercury.jpg", + "assets/venus.jpg", + "assets/earth.jpg", + "assets/mars.jpg", + "assets/jupiter.jpg", + "assets/saturn.jpg", + "assets/uranus.jpg", + "assets/neptune.jpg" + ]; + // although we're specifying all the image urls now, the images themselves + // only get created/loaded as needed + this.$.carousel.setImages(this.urls); + }, + load: function(inSender, inEvent) { + //enyo.log("image loaded: " + inEvent.originator.src); + }, + zoom: function(inSender, inEvent) { + //enyo.log("image zoomed: " + inEvent.scale + " scale on " + inEvent.originator.src); + }, + error: function(inSender, inEvent) { + //enyo.log("image error: " + inEvent.originator.src); + }, + transitionStart: function(inSender, inEvent) { + //enyo.log("image now transitioning from: " + this.$.carousel.getImageByIndex(inEvent.fromIndex).src + // + " to " + this.$.carousel.getImageByIndex(inEvent.toIndex).src); + }, + transitionFinish: function(inSender, inEvent) { + //enyo.log("image transitioned to: " + this.$.carousel.getActiveImage().src); + if (this.$.carouselIndexInput) { + this.$.carouselIndexInput.setValue(inEvent.toIndex); + } + }, + previous: function(inSender, inEvent) { + this.$.carousel.previous(); + }, + next: function(inSender, inEvent) { + this.$.carousel.next(); + }, + getRandomIndex: function() { + var i = Math.floor(Math.random()*this.$.carousel.images.length); + while(i==this.$.carousel.index) { //make sure it isn't the active index + i = Math.floor(Math.random()*this.$.carousel.images.length); + } + return i; + }, + updateIndex: function(inSender, inEvent) { + var index = this.trimWhitespace(this.$.carouselIndexInput.getValue()); + if(index === "" || isNaN(index)) { + //enyo.log("Numbers only please.") + return; + } + this.$.carousel.setIndex(parseInt(index, 10)); + }, + trimWhitespace: function(inString) { + return inString.replace(/^\s+|\s+$/g,""); + } +}); \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageViewSample.css b/lib/layout/imageview/samples/ImageViewSample.css new file mode 100644 index 0000000..e69de29 diff --git a/lib/layout/imageview/samples/ImageViewSample.html b/lib/layout/imageview/samples/ImageViewSample.html new file mode 100644 index 0000000..1c8e7e5 --- /dev/null +++ b/lib/layout/imageview/samples/ImageViewSample.html @@ -0,0 +1,22 @@ + + + + + Image View Sample + + + + + + + + + + + + + + + diff --git a/lib/layout/imageview/samples/ImageViewSample.js b/lib/layout/imageview/samples/ImageViewSample.js new file mode 100644 index 0000000..89ddd7b --- /dev/null +++ b/lib/layout/imageview/samples/ImageViewSample.js @@ -0,0 +1,28 @@ +/** + Our map pin icon is based in whole or in part on the OpenStructs open source information and documentation, + largely developed by Structured Dynamics LLC. You are free to use this content and system as you wish, so long + as any derivative works acknowledge these contributions. TechWiki is provided under the Creative Commons + Attribution License, version 3.0. - http://techwiki.openstructs.org/index.php/Open_Source_Icons +*/ +enyo.kind({ + name: "enyo.sample.ImageViewSample", + components: [ + {name:"sampleImageView", kind:"ImageView", src:"assets/globe.jpg", scale:"auto", classes:"enyo-fit", components: [ + {kind: "enyo.ImageViewPin", highlightAnchorPoint:true, anchor: {top:79, right:224}, position: {bottom:0, left:-16}, components: [ + {kind:"Image", src:"assets/pin.png"} + ]}, + {kind: "enyo.ImageViewPin", anchor: {top:280, left:415}, position: {bottom:0, right:-16}, components: [ + {kind:"Image", src:"assets/pin.png"} + ]}, + {kind: "enyo.ImageViewPin", highlightAnchorPoint:true, anchor: {bottom:"20%", left:"400px"}, position: {bottom:0, left:0}, components: [ + {style:"background:rgba(255,255,255,0.8);border:1px solid #888;margin:0px;padding:0px;width:300px", components: [ + {tag:"h3", content:"This is a text box"} + ]} + ]}, + {name:"testPin", kind: "enyo.ImageViewPin", anchor: {top:"10%", right:"10%"}, position: {top:0, left:0}, components: [ + {style:"border:1px solid yellow;width:10px;background:red;height:10px;"} + ]} + ]} + ] +}); + diff --git a/lib/layout/imageview/samples/assets/earth.jpg b/lib/layout/imageview/samples/assets/earth.jpg new file mode 100644 index 0000000000000000000000000000000000000000..328e8c03934bf23de82c67845f4a18dbac4289fd GIT binary patch literal 157230 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 z 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 literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/assets/favicon.ico b/lib/layout/imageview/samples/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..52c86347fe3e10042c05374362757fa260307d50 GIT binary patch literal 1150 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≶vOX3v1YT*-6a0P-=iHnEYXl3EJto&@ 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 z z3#Rv0*Epn57{aY}oZvUVZ(yeJ;43; z{`g12M+cLG!EV7;E3K@_CgHB`F}+{Lv~S=FUu^YfA{~wV6=8ZK5LAvg*ukv?=qpa0 z3+HD$`b948sRiXO-{&SPnmrga4X$U4)qiRytrDCWnNtES<@``ri#OWpRd6Ze)nmV` za#dUHOJM~FmqLMJ|ir4Fw zBa+3WhASX!P-FY2pC=41v6e~_??phw1G6?6+;z2Uzp|;Q za=vE5Vl0;pI?H%o-yia^c=67a5)huYnMn_phYP0JD~E6s`Sk>SQbAuSl8Be$9Ly`b zPhm_O%ytxgN>`IYugwK=4mEetSJ@MU_qaTy4+U#kOr12shsNO|76#d5x*eTx{}uA@!F1^as`U2;$>0=y)yc z*FG%Vk~B=r!Kdj5cK#1VV{gp!tHEEVUXPk}ht8-8RqX0xHq6_f2rqchjWsc=0DGLdben&ngn{2O>YNaN8j^euI^?FXtmoqzxCM?T! za-NTo@Tjr<%lC}U72kQO#Es31+Or`zQQ@Na)I<8o^XzQ_2(neeTaui^Ogi-_}sykc>R8mHokz^ zQ0Tnfo@aQ38#!{DU!|}MZuFgjV*yO)gEFT4zD$x&%6xv)6ps5Ijj}pZs@CYLY9&DQ zW!6DwAz{k7g(RQ=`ITAPm`pQA=5yXvLF?lC^xq8FuBM#IUj4%sj^3|a#j=|vY}3xo zZMuO<{M==nYFgi{4EMuxdzw*meg+kCvg&dh9YeF5t3}C3i1z*ozwqx(>rqp3ebz9n zJ65>K`KxcoLTj%p>}naV8dg9C*q-$7oA~i8fveKrwpiu*^`k$!vSr_Pa8b z-pS`7Hn4O%;bciLyQQM1>oS5Z z%5Y2eRa6^&zr#l}xkAw*L0&4~p;4dEakv#U!vR<1|As+GE{B%-GwWgZYN@#nInL~) zuxj4kbI`EelGx0^$bPO|2^$#bjR(a=ij3Qp#FrMRsH9J(%!zBximRt#ld}BSrI5CP zX|o- ztBQ90BHgieT)yfTh`LLnp8BxFckyneGYDS?pg|!enicb=lENYz(lt^Aee)@|p)@|% zUEtd@35T|J5ylwAPcPYA($<*3lF8UG*(QDjFPz3Ys7fZ@EWXQNma|0QKFL#f%&4>stROL~_e7#D6 z1)C}ZxCTjBn_EJ5;qxpik!*T-!%L;Jjl(=g13Ep1JcbMK&o?wXd7Z4oN{gS&`RGA% z{acOB`H8jNFFNwehJZ%w#;aK%jW*lauAhVYkGk)cuU4I>Z@JQ$cAN{@6Yn(R25%L z{<_MW|EN_I!yjpFN%|`5ZDb(*+Ul!+MfjNVKwC|F2RZP%F|-qw`l=T8Rx$A793=2- zbpZ$z9y#TwT_O2FX0WBI$P%3-l@`J772`rKp1D6!CAFX@-q}L<6u&VEr_o?2e>YbL zE4Cp;0>Ih-N3i`rpMU>H(PhR}cFtwS@(#yQw8pIrHdYtifzynP7TD|wi}xcu09VyT zXL${Nx2c@NC-COFK8?kZC&xUdjHhO)W0M?6j=&SuKML)wXDGR&a*GfRC9-wH0JLrI zu2ELy@k!Um(1$&33$UoBiuo{!_L>=%QrnxYHh`hXmFU!rf*_5py>VU=*B9#~;k>%*)!W14{CSqop8u$@2RS6BU8bXaIP|8}-V z!@?ryVk_AB9Wo=8n%=yf!2B;B-aRce_)0jdl{N@$W%1GPi-YD?FOoZxJQo)B;(qP6)$E0M>;q9G;+hxC* z;V#%KB48s6LHA|3Kr;WL_R-VAlT_m!*0xPUg3{w+z{MRHx9Q zIDus3yXu3EEtHQQ{dSmHN{dSH%ziB6yHp&S!hogU^BnJ(wc^5OfeC{{B>qtYqHcP{ zhtxffBDY+%KQ<%!bRP8$^_-jaHx2BksZ}`!$vE%df`-W%02V=_s0$(XCcNOng!8O-Q8>#>HXvF~UO!p!4C>nK&VP4s zUNwX!8}V@l!Fm4G@c!b_M(;GH6I>@U!ZniftyQfCe=%;kujrmdWOLaC@ z*`bN*4j&#Pn00T7e9wH|`k^r$aM@fX&N(=&N-mzpa}_O+8Etg=@n6k74a@Y>w{~yE z$&5K8o*%aBota(Bg}hty?eb&MsZ&h^C>m^GbXz!I8?Ig`rg0(LLZp+Rp8RwHgJrB{ z)hrEJyRNLCL^(i`yR8K#=jD0X-~ ziA0l}xZ53h2H!8&0)&&31pSn=Xr&-By6GNDW51K72 zUjFNKNtsxD5K_h(_)c+Jp!YgguJ4|$0iYPgkaktt5b?=x%L5JW_Czfh|9L=@S5$I3 za5}F1sJ}&1A6BKn@G~~M1Z~=_!{qa-Q=w;XqPxjNjY-u!It$FGQ56d|spU)9iEI3b zyc9cC#X4|&S~Y^DYl%Ggs^?Hk>7*A9xKq))uZ^{uN7%*VM;ItVMy7xiCW@s|5{Frp z?SFV$9I^R%BPQc!-tuH;9M7BxO(;@zZO1HhszSr&9%TKaMmRHFvge4t$#2dqfLqPN?b>yxXg zt~VD^%H9;=$cM2nkV1PRMV?heK*q&jT(yOQ{)6Cre+jPe{I9qC*e}9cUsqC$ap{N~ z4)DMcl&mlG!7|iClslbrYoifN0ADI3cuaWyhZh@T#s*ZF+_%p`5J)LwARm)13wPq{6YAviS| z@kfgArjy>bMOTrbc_j&`YRw@$qGW`GrtK8pV$rK6It|a#NX~)bJbp z;mL45rHaHlAu9m~xjxxAVu}$7=A&Z_)~p_}O?D##o0`zC2~YCpTYDR7Zf+EHM~+|< z?|V+H=FOjfP5#Y3;KprM(_o-e^XL>1Ou0}d(-pd}c6gRGjDoEeczTE`nNlURMblf2 z8Yy#+$K`e2rYi}bRJvE1y7zd3QFkrrKZ~7s?d$F4+gVgi_&D-uAjZKL)1j4A9+lf2 zp&F8e!ol-c-!C0neoF_4_H4rY+0a$=Y5~ZU0M|8{$XfG*s55_YK-J1!j8()}pIt^n z&jkm8O_qJu_lgq9>G%8@QxcqQ0_xG5YHe{3-){cKIaKYEUvnpm?5Kn*{X_v#(nKsZ zWQ&;FL3Mzfad!C*Je{;odc+5$P-jn{`-N@>$R*X0?}-#^!|G5nXYj*~eMev+y&W4B z+vOYHjBN~68;0>@r^BmCOi!bI1`E%BX60y_pOymA$rxt*nL(j*Dv_7?>p~*o@U$If z{nLksPgL;g6HmKhIP{U#-H3Y;m!0`Fb9~#?fE2Wnw=&9KGj#T9{Od-BsL49Vur4q> zC0G3OG1_|AR6;a)w>F{7;jAz^z1j+2sl7!|n=(Jmbo;#+=n>4;Xbz`7^pIkm>i# z8k-|cm5;teT3`~*-&Oyi6v-ndnTzvP+6z)ji{!KKF$`G`e7-hpTaZ){x69BWE8^?S z?15Av{^dkz{C>(kjp{OodWP@Puvo-!!t2wmVUy;GEQhE1)9l2Asjm6{%nI2M5k)0~ zx;HGG1a4UeviKy8NTnN+oErv!;Jh#IxG~IaNEREf-xYhdhQ2HLM6LcvQ6b&%(UtUA zo5Rxi4^H6`Vb-3E3-3l64&0~+>^G4<678@srxl$1{7RTjFFCNKi8si|Yg@Ze zAlQ58K~K`M&;Vc{#~j0ja*5Xb4xuk5PbA0rF+C+s#$c}UHNYZK+Yurp5Z}{NIcix) z?ZanL@lL!Pt;iYFCa5Z(KiK#Fi0qtk8>EXz;z{){IU}M$^S=9nB09VqS)aTPN`}f#C$B0TAC)p<*5SZ zYr0T3EudHwaY35)ag!>ZIiO+qZ>0OzLqbhy|D6lyk9m=St9K*+{}f`{Pmm%MZ30}k zPgl6fbpN9$bJ8(n%PKfT8O7F#Dju#MNm?Qh{!U@ER=>Sr;&z|_!Cc7O_16rJ3uq5J zO=Fx|_RE6_R5l-OBR-I~uILD`(c@(r`sM75xIEj%2sD(Q4C>YKIHH1swF5Eg?8=C~ z`J5R*MY-iI8W!x|6fvDs-@fQ5*zlVC{)5&W3R~OyHWSr_$fM+o}^N<{>200218BJz};X!Mt zeKDp|n1zT4U44a`aJX7GXhNEoj|8Q+^SyW}(>Usf$qirS^0XXDoI`x{($a-9XG%B< z%5ii+)bwZN+w&2m@A0zbn@P$nS?|k4Xn7dK%*{sB?`YL7JG@_1^#$96!UjK{gs!aF z?8h{7s>nw`Fn<@uTmD#y-?D;xhwn6Wxe&}ukFBI*k$I64Q8+`#>jcFYB>#@-E7V%{ zc@jG}WsD3(kQZ43g1tK;R&9f9#>~sAYlY+R%kT;VM!$OlsKQ6Q(2|^zks-IkRWgyP zpZ&t7b#ZM%1DP%*_9FpGzq2jkk>Cbi&pp)rrIs`|?emw@M^#0mN{5wcYA!)>ZTzv6 zpkb$AywZ;+{SN0%je~G{;M+IuXIm z2G_&OL9yT_8tXTS+kfR4R^l6yXovCAH-?Os6DF3^BK3Z!44zEJn$J}g^e>Xy#u6TQ z=Nj(lik0wd-{@H{U3v(HW%V|HtR>lYnB~bt7q3wH=~1N}8xrsMMP^~MT5GEA(=hq6 zXIcq!^L)MGUrfL4U#TLbuw+r8PZI`5F<0h_gFgn_W^=+_`LjCt$u$32a&W4Uk5&O_ zkR>38v5)gySCc8~_RCwg;+jP3J`TJdU)1x{fHA(ua8A+g)t_Y6TGwN^u=7x$d%@7db)z-;|MEtxVqlEFywI2molt@xxTZJhY zKz~b;zkjcY+u`GDC93dSS9VT`^KNC@GA6Qd-dHwX1T1Cnr-1E)=pU_c$saz>PpLts7w$fl&)#79f;n4n7z=-r3XJ$-M zm8i#@pP@oGR=&JTQrO!hq93&jR@1~6e%pT4R@MDF6dJLa)Kflon#v04gr3FQin~dM z8Vnpvc{h|!KjKS@boC@hnyZ!Q&$DN35&FllV|4+6KCZq5=U8teNi#@Z&h8#t!qC7b zbpbhoxB$K4`pw*au~u2Ii7VxV5IVlr4vPs-4T_cU;i_%7Ymzs=yd?{pm4Tm>F*)Mw zVHL-Ji6Oq|Y%R3$tnt^->*LJ(Bt^j$r~TQ4n`yxa?P1bBcVFIP_K#+DkCTazReEqz z9k<}lU%JgbKD~5p>oI+c4Tq`;#)0v?Fud+Jidt2TBB&xLYrD%=lC!Ct0z>g2Ps{HK zzfP!EEfgGDRNIz3FpbWrLhs+QMh}QMI?jU)eiQ5hZ&?0EjLTzVdo9aL3wCP-o2 zz~(erRpfmam8~IP2cd&;*_{+qILii3&1CJDT35F%GakyUq|!oW7Mm?{Adr=O)xU#n zGITQq!vR}ovgb*&*3hzjrHwEq(Gi?djL~FD&ya*1cK;<`y}bRtH8}7fo;EL}*mFm* zPGrJ#K8{^}&^z%<71MhTrYzf{Ovk)gWVf@u9><)q7B_0O=h?BI`sPmb;rRWO=bX51 zr>n|}^m~*o0&V}qOqx}Lv&;*%zl}b`WP9t9JTBqW#QS`|cWOD#$U;FZSEqw9MsgV_*IbOjp+`I2Ij7m^6%1z3( zZ=DVkvCCHM$vZabx7sV2*}tG~(6!F-v|VZ^9A6NlR7f@%NA|-xRc)C(B8L2NF3WaX zqR4MUXG7$-1`qYS3*vdQe-nfN8WAmlKpHYf&kVD9ZDeR37rSct_F+>h%Qq)~`NH@E z&?OV>!;e-K?-~SM&x+~~2uj~nY?I9E6BvVLVwb~Tg<5GBH9LcGu)|{nH*hSq@ zorOB84_k^aDt2k59qGt)HD8~5rJ@IW>ynTsWqXfcA}yG%I7&D>m@IP#w0vUx=(2}t zV&3ge`xgtQ{>+yhVw*OsS}3b+>0w!=)6JH686641XvqLjJvc1Yv%4tac@!77t7X{w zXpO}8j@sZfzkeMpEtaW=h@lZKVn|WfP>k@Xi1n^xXgzpR|EitL4k>tcGgY9C>jyD} z{hd_X?(DV2w4k>jf+(^X^A>sxCnzS5FK&NcE;19hwJCEq7TxqUE18m&=vk#?U7&~Yk58nBG(>*lHDe*VH;(n7XOrLA8TI2)c6<#_3+I-33N7}c zZ~r7wiVGN1TIV2i4=aB>Z zGZZd$hqK{p{jHZJIs{AiEn>95`Kcjk2P+!s%FRZJ!^z&1@4ylEL4X6*uGhMHE~4=& z%WW@R$TgPR%wN9vj3vdUX6}?M5A=6^AO`=6>9(c44_O@?EHn99 zX4Xu_E}AUOSD@5XR;=Wg{o>_qGG)+G1t}c17-zWUW`&}g9Y#`a^Jg{Y32=O>Qb*V% zt$GI5;N%s$Eq6DFR#UrpeGwh3QK2V1L>ZquTOOS>62G`ql`dVn_xz6_cl|Ve7JKPU zOehg*6SqJ@UB7NOGg|4OPZqb<)+HXi9Q+2zlUaIGq5A`L%8cS6kii}uhG3~_-$f&m zt_-!zcS{eKxhg`?S<%f}CyEGt#MI5Q-Q@Zy0hH#Rkj0O^q^)*xs#;(%YR;d9|5UZj zBe&xt=roZ1=pEFwxy`~ge+aVt#gvpeR9)$YsXk&R@oO=OS* zLA*q7MNu=Odw8!@6;59pN6vMaX+e^CDZ!vm6Rh#vwk=)Xq7p176h5Lwr$=L&u?8KE zll&4xK_8G3-A#XBH1<>w=)E{5ji6`7Yg{=;QF4;Y=`i4*g*l@%@$@CmK)diIB*NWG}y(>k*H zA_L7lHU#NbJ}<}Hnn=0e)GCw*hK;3tQ0b{bBop`$sF^bvNGQX}DbcYExh9HsmOQYE zSU|c|pG4lJF4$`<)#kW-T$11;x2;h&MtCW}8`q2c3W>eP?}mt5)72yGbd{k3ZH3<` z@n#}qgK$D1TKlm+v$V6vF%7gE04EuJ+&muxuBV@wK$`zGG;mW zo%(=*MjC+m%ZWrQ{_#>-iWGnqxOO*cF`;vwqj~VAC!~1ExT>FA5|i017qjBPy9P)7 zS>nQHPPpCv^NGF?qYXPOrC@Sd3P;cwRKb6p_SZ<0K>nS|q?6Wn7X`Z4%#R+o*VonW zhMi+q2Pgl=FB!#$C0c*I7u(qa?P`h0-oGCbW}wN*a@Mb{`u?LFY8kZhnY%#U<;3#+ zh3xBa7!gD_$nzb>vrD6$HJh)cp`c^LY~zf+egtqL?K^K6Fam!IgTYx*aJ6Y)JINT9 zhO^sJxq$2bFj0OHE!!zki;;(>4$= zH1JcXtG5Xt;vaxDKl=4VC_oQ<(|c)1anw&n$8F{!jWXGRHm~tqqW7XZ$OW|%UTL3V zd9P}Y7=pyGAAOv_2f*Zd2DhnORm$Ikt#Y0OE6N6FQG?tP-4)$sY%w1|RikA!%VAE| zgLG_nQ3q-^b>R|Cge>!~lS|>s+Zf=sA5GiQ{fE|dFRB?~2{&T)?9DU|H$B17gq3>(kq&(ZS?2!Hn7Ui0y%6>_O z^VM@$fV@tYY$bh)jjTl_VQw`vn?$IaO`>k-Cv8JD;l)*3Ist*Rq9@ax)>FqB+q#>D zx8=~S84X5!W2G84cHas4zvhhcVtLi=7*-M0P+Y!HE3`eHr;hUBxgpyj#;7|A1Ye(r zDOWZ8S%O&VqETAeVGx&7x68hy#J>&uI>p3!1KBpgXiBhcC2jCstdM>3we=jcSyFXY z14mLtFM}`x!&hFr>^SRqJE@2%Elra-t{v{~U$O6$~DdwQCM z5o1@%FD$s8pMxKLr z-7zc^Gne>rBDNLMXcxiheZp(-0emH2-SkXL^_JYZjAciUw~lWHhO>;U@9FqFCTuqe(uig>c&GMDCwS#b zK3C%PJ8+Y8-fy8*C)1IZ8t*jjalOfnvSABXp}FL{ppJdjc4{RwwO_pEi1i`Ye-p^> z^^r(7ATzi!d--9$BxXckLyrWcW+;!g$q?_=$zwpL>cezYjDFVViRX%Je?d@BtnW{k z6x;2I|393aWm}YCxUNw^N>C6Gq(pK+KvKGEh8{{7LIk9{kxpqC7!Vw~V`zp3L28DQ zPNln3+C6Kn{bBFpSReMs>L8 zCI@YyTnhce(w=eM=u?})q(1e2qOB#fbgnkW{!yMcNs~9kd*}c^m(ET_p7ldkFSX;x z@~D#q15gGtZdg8x(lkb6x1KZAOPeJ(Of_%(@OIl@qS)+s`t7&s=M#($%ZYfrOn#r+ zRR5@}LYwJ2*kXFwAOR?$JD*4D~PSO))^;I#P(W4j1xn1WCr5%gU_E(d29)-w~$ zXO$NhOZjURt|;BThrnj4+S0Xn4b%t%sPYjidNVV|xxKevu^;pc^xc7(G(;Jp4HSEm zuE3p(7(rpPJ=rufx ztw*2u=X2&*HWWFHeU?mmBf3c7Qbf3Zba4veR3o2y z%{ud#VW!bU6dX*eNdSQBSNrv)AM@&3cojGG$p-TFn}@H=4u1To}wo{o1D zC!G{c(1CCbHJp~F@R@wcmuBGAq=~ig=mYkCNjzi37m*l4pCAYJGl^Xi$}($z7rYTe zh^&;!&ZKx?>Rfuwev!1|$9+r7-TE(Ud{^8K(n4LC5^()G_|i5^t_CFfZ)TDsFMKrq zntNRddhZygrApA12q5Nh{#q#p4esLWL@b`B#Dis#i;kkv8>iwG^r|c*#GU=8N(B5C z^9A!&2hEf`p%h=Yx1js_K9kZv&`Jv(0rw9k0dG$_zzu<2Gq^O9v8l=>pJF300SW+DX+z=`s6a-TxYS` z)L(m|kJMQeyna7e9%X$d5V~=r=WX6gnOsXpQ6&C8)Bi`%?0|+xc{N3+0;zT6^fhtV za>?X$1qHV%S0u#DF;YZ3@rg71vSLaib-R!a))%70`+@H7FvbJ8k*EE<@@+dy?HX_d zoE$n~em(6rpQpv-q&bjj4x>(d9K40;0;cHmN2|8aCH|U7S?{N}<@}^<22_9Y7`E$w zGwnke!&WzvIti^1h3!Q{$=3$-zf!^z)z@SFIap}oa4vx!9W}@$1S*lKc+-zRjiMH+ zWM-hqCHi)bX#BkhZ+YXNYlXke)F4QripUUenyKcQP=5OPj7W%rEp7;Vxqw;jr{xipsbB`+-`Vti6D6~6QZAq zPZ{WT1r}TLv$#aKRK<&NvY{18-lmzS89JN&f9CQd`o0s645$_o!x7%4DuuswZPs3><~GB1j7E5P+6C12zR&7s>->|ez6 zCE8ui`=UgPMd<5EC3`qUQ*bjqBb6Q>pUedcajfJ|{+(Bfa4JyTtOBn zf>o*@f^CL=!asraMXy7VGVM(@tmVyO;Hv#MaU&!sv8X_dmZE-Qj=-LIjpjD=*9G;F z;c~Bc20%n74r`R`!nlmGaEfx9gwKid8sAmUg7qDTq~7i0cUU9WOKus5S+oxQbQg2c zaH#8DMt^h~N)MHKY$D5${HTV@o^;DQfX`*g<$klJ`V$!0&JRH4e`pYy&ZHf|#XV;} zuYBN86jQ1JsEMZ}59!YMj%cZdp}EC(H+X)S0XBBYqzp%(5Ux3ABkn?6tdeKF@eMB( ztZ(`Sf?L$dy!s2(448+%U%`sy8PW*+!yh)Kg|%cJ$RvLT{vD>2YGfTOwT7BFYV2}x z**2z{`Yeb!a%dlBSz_si#hNo=J({`JS<~ug<3aH?bKFq{W{%@G)UvX!-j8vUY0fHz zkRth^ByQQ`m4B4D-1YJy`#+3mKG~I}3_cda^noQfrWC}u3|hIRm`K?AV}}1>sb1db zdRNX^CW|AoGoS|1gwu&Sypz!r8PQ1n_;U+{P%$^nqz9w%W9v_=$G=i7P_xmU#og$S_?Vag8xsnAKUDYXv}a=C7yFOL zs3n!EJeD58qF%DaKETRhFFj3v)FC&B*3qBUqAO_iq`^7MyedQ`c9lM`mBo3gQl5m_ARp=1J2t zIxPf^xW)IktDADTWEQ!p(7-EE6$C9(8VlT-9~V|wnF}dsv2@QRJ53t;rI-W|bGD`RUCYiDk(Wsbrt;G>1#NWC>-yn+=tWb zK- z4JL!%2UYzNH!_`A(G)nTx%-fhw>?7?ce=$XA~FgP{7sjsfM$pfV^L4cmeE!Xok(NH z*9YL7d34))Be}>8bep%D4P`zC`J`;gX--_qSTetZfHZfpMvpTPqO5~qjJVbD&KUA6 z!+NvK(JPK|PeYjjeRCCU9Z@Uk z@cPM7W}js}8b!irOKp4ITF0|M1&*e9n~S^rXfH@CpdmGoft(Cz|4kk2wcYL98rM>% z@1p+Ktr-oOS7$n87J^@KC1I|D=mr)qM*kqzudZr7MVmIq`mg}Rw&QlQm~FE-Pi)F{ zVYZIHCNT79toVYgHAh%XS2UH6MhzPPowOh%The0im5(eXH}!|d=n9SReJAKlJl(g@XwIiw@OQvT9s!N{UbI5?8=!(HW{S z95pl>FIJKG9(Vv3Hou!`bzaABJXXe)`diRe_#8hRBulm*sk0h_>5*rJj#uR4^OWU5 zoN5=*M)HUTtV*+>x=CHjIF*n6?IAfbJM!BZfRILtP3FH(D(it-8(5*$PwMQUXkHa? zV&fz5BNRc|b5oO|BENo92YM~jc@@nc|)>zzVXq5V?FZ*Ju|8C8zQa;veKx++t6H(SEp1CJ>Ohp?wQGU7H=0f1$ zGy#D}M+ObG_SdH>X*Og~JeWMYZe=>T-q+3_1bT`mvFI1ZHH#>QnUf>iy4ob96g~rR*Qp7t*SiItD8dshxCkC+yES zWW=7r9c}4up3rML3Z!!>c`JW>Tlmb?^{jvn7TPq@PhO5onD{>lX!~n$`^_=U=Pu>x zev#DqKOa>Qa1$Rb-ZN>8M&u8jn#99aU~|L#d^npFD8@!G6&6zi>=5WgzOa=w{-GQ>iE2$c)0`t)q?Y*Ds0+9S~Ud*ATxX_ zW8o`Y!Oi#tW22eE;L3=TV18{vqBuDu;L7hWV%Lz}4H1I)_pO`&S6{}Ke^@%dxuNq> zZ@whw$tyc_c(~F1Ws^7s-b<9%J$-{Q0`Pu!l9wnvZ5mwp0C5Zt(EWA8Z^-YP2O;I= zgEXk{^!O9F*eUk`u~M?zE#tX?t`HtJ4Mn$bQOBtgW+U2W=q|*}gowZ`vD7Me+mm6^ zpTtBRXkHMr8Vy6rIl9r=a}@)B3}AWQ=)1ou75Fr_J3cs$h?lGmFowChIb0=xVqt+O z&b+pgp~1+J!5^aGu2;h1yLe3(J6e?pQ-x@)8}W11IbS7JE;fk1qyK8La^iG+WPTo?YdXT7A!ao zPFjBE&hsudKM%o1`-PCfZ>;DpZ}qN@2bsnJ0CxDym$gX}fV%&dVBNGe%I!fWn@;LNEET@2*r0B- zfx%I&JHK}~N(F~TbRKeGf z)zG@m5C&_RM5+J&=EA2?`@xVfShj0+c|Q;|CaK^nRM@#nFnh!C*T%Pt(&9FTft#DV zd}tQ1!LdPb#)-4$jAy);bhR@KI*-#+6I6uzI+|>v1}Yc$@`Wr#PSyHdgxQ9&eP3&W zK&Bfbwl^FYW`C2Y=x#YI?_r!On~Tx;5Xg+kgF|Dz2=6Zc4xEY~x|AvvZtwo=-T5wg za6FAdqSCG0#bIncDjzo-*UDfQzlC3o{@b~+Ai*Xl_#@|gvU=>F^Z?k zfnNnO2C!qjXqE^>`1k~V5zQZeUua?UA33!T55H_;Vw`nqi*@2%vehu!kf1KRVZDcx z#zyD3N4Fv0-G$b;4mKo4jUy+Ta+vjY_7_+90pV@}yFS4=+}2O^awm=(aByq*I9-z_ z8U06R8Xo0)|2+O##M-|Tc(PS| zPz&ks4s5zEq{#XBT!?9gp$ehBredu%^r|sTePH4xol2?dw;76o-5MAsh48WxC{^5{ zL|!8R$CUFwA>P;azES}#t(rJ+Sp7&f^G>}DF+z`@I{Wx|Zf;(li}^ZG_07Mk!@m<$T-GoomAcUXt8DbsR>~hqcqtMz13I(2O6pnP zlZ|S734D2-jXl=gVl9l4JfXu7B_Q+;UVV{=b6oW8TmMt_0P%B5qHhoQqO!Z^QLS( z-9_esm7}zvwUj?>HhKs45E$7RL9ZZ}*?4VzF%vZv)dT0lN#A!)oO$&juHQ{ZT{gC8Q_VTKLJx)SRG!Q1$g1b` zE={Ndpj4NIKJR$gYmvCW1I3K8-n4KO*48Jnsg(0E5>~*#t_urS&Q_@eN2!$DEsS9+ zdY)_{T#4pjJkOAY-XM+fCmN~~i1yXfNq2w>rLKQo_-TV{th_`qv_2sKE_P%Bz2ZJCe>C~rHS8!M@L^)l#G=q_SDfjt!hfDHjI zf%2||9sF0ApY~{D%@2g8UU%x=@#G-Dfm+i!uH#R~9O9UBkl_#<*pMAJ{;Q~1nAVv* zu1oMTZu_((FMT9+|lqyj&en4cA-&tEb9J<8$~^vC?&4%I8lGvM4ne*nm0bY#3{2flGwc zqqZ@up~@TtKTxIZj}3}Hg6e^B63>d5p|0pr^NCxEl!AhiTHU&jCLY7{Cc-&djNIZAbf|DutLlg*WY_Pjr;mMrNgkviepQ{sUAkl?^^{ z!+^P|Y9k|;MG?d9B&5RcCID%aY8~3W|DDQ5*|Zb1zVHQ&gLB5lu~6lNi4lMz+jAfi zk2HUq+353#5NS-OS!lHhH=&xW-r5 z3&v)@u&jms=cuds)FJEtYe)NEPZMHc9Ciq@QT~#J_Agm)=GLw?6xY+l=gkb^>N2V+ zZ}MqPFKgLBcrnIbN0993gy8R^>*DrVi78 z^us_RD+Fje91Eue(5rpCFd{G@%WxeSf>GYz`jxsEF{@@GW(twNfwO6F!RDrn@WY(Vf`f8j9g$9E(gQ z<>BJFW}Zcvh7)zQA4>HPzaVNXTMHnc#4ZkDkh;wI&fZ0(s<&mtcaP79w*Iu&JqE;O z_T{=ALtj_&=pe)EC6D=l=X;BP|5n+N8-iS|1hRIhzOdFbeLxg`J*M`+5JEiG$)v?B z#V!!^?CYL$ChDS!j!e9r*0bcpE9%^aU=tROA+Sbg;Q4u1g{1>X-1i?=vt^m5dR5w5 z(cyCojO_kBANDpNfe`^$eq@B!FY;s(nY|b>xs*>?5;X;EO$Ri+K4RXF*|4hM!&oeJa}m(aEWAuRde3 zWx|^@$7}_01wWk0%qNjJ+hz#H^^KMAWbme!q->yP99-1O#H^&aok>8x!EqRK6lbYL zn3b;Hr`37Jct}AfX>+t$kF4RKjd#H*1r~w2uf=1bzZ7FAW9kXc1^2t}A@FO@$yFL^ z18iXmt0cKv9SEOkOU)30ht#_uJV3wPpOS@vddTIaRx3I|Vu_+iPLAp|eCtnr$SM-7 z{wG#;*0~Bm52~}KtnAf31k^Kv4ED44bXxXn6|7GoE~?0e(&nctj2vR-$cuW5l8D$C zW!WMYh0R6#?4IPiT{z-}lG2^1^UXq;cl_d@kuIuE(Gb!Tsl6(^LKC0w*l+)FCVA5m z+N)7lOs<_-84p`k?4*4^6Ln$_ra|_``LA z{ILyxKhO(A1h+EjiTN2(4+$0P+ro3quY&BsLc+9VEFxlAKR%Ur1Lh1>tk|le^>lVs z*3z!cMyzxoI;^MR7I1Uyo$J4qsvUT+Ea2L>`2IDMyTb#PORL5QwiIC+*Ip56o*rqE zf^)pd1c#G_4u=F1C(@=3y_k=K*W2^HOCdMvw}c+2mc#b7C)Z!O-iHn+4G(6o(!{#o z&d7zCjP&ET!++YYc30#b6fvE)l6^`ES@?(5UDd5Fc5r0!W%vZyPTR>wplcnp%S9mC z_pOlzvWYonP_ojvSeFZphO#OWNfpsi{XaLLIQL4d7)PUFtxJ>L;EED#mu zT_z7&aS1+)D;x^TrP@%lp{*~av>ggOD2XjSPR;(%M+y&UXylgNt7EbJdYF4WZwBB= zSeDomv4}P19cXU0DG$#8ziLu2Qn$~tB6F5{J7y6JE3!dR&8nsIEn->V?8ChfI^W0H z=OOkz>i&UzIYC%E(b|2WEK_bc%*8J7tsDKM^{zfjk2R?MJ=ge4?}Pd8HZx=? zVNdnrJ!lV3B71KwBNZ1Nw8qm4#6`$fx`;7A;%%j3|6cd2W48e)|M!yYG<_X_6JRVj zdAtL8Pj6Z3+t)aWw&|z|uJJ5+aO-YxU{)mqDgN z89z4`?&aHqNciHHG3`7QYtAB2#oa>*=YjrP0E*86)zfL+l0cAzCi?n1(fNzT)*f2u z(9ga@6`^mvA1?@b@0on%P;1DI^7*kaeF@Hf6auF=`)#WF4Bc#*>UxmDULgCx(eNa# z-p0#*Tyrrd=7;y&Ai}Yb_m}^$dhOP_9lgk!UxCsot_&tB1AeyhJJ;o@HUCO`EOK0b zMzYq#C{^5Uvp#rWv;UQghGgToD(BEewf}7(V2I@TM7g5Gz_3MIMfsdnJkQubo8q$0 zFo9b$BfY>^c0(B5k3X`>nYBs*Q~PG8sq$%c86U1Pc6>i;#WSA?%&6;4R=mB(yPYu= zsJBw>Yw4cTkEoUlt=ZF@&AY*iV{}+p7&w7#_IXuU>{)h(y3Dz=CjKgnYUwj9WCf8G zIh_3c(YMj-aQ=ho$cPLD^$o6#HqPii^Rm-1W|0f|6>9sj)Ma)KghlIEd8;pP-V52! zUsA{yD(0HO=SYDGlJ*u{MN^%=Xuhk{Z(tth)Is%*722VqK8<&iIz;3w*vbZB+4EIk zTq}lK8f&JG!%}WzL6e5L7a)c9yeMJ?dTOvQCxdz(f{FvlW8v{V^jBece;~|SUo?3_ zkc;&z%d0>=qFu}PCA3@7PhNph_j3|1*~NPwK(uyI?nkw}{`J*i%sq_f;bi2=n0jf! zk%d;U&>ZN|c=xY4@myOV!RR#NQ%o@z*|HEl*jelpz6wwNmH*zccT_D!S(DK66hiet zhIheQ?VDur@h}Ouxre-JMC09t1YnjY)7^;PZ1XwzSdn5$OvjyoQ02V@$IUhLvpg95 z97AWjz18zqZp?SoFl()PYG^~mK@|30!VUH7evhJ*z>$qZ{M~99bid74T$kwoEqw65 z2iyO)NXVew5)Rsr9IL5kGH_{c=iK%atoIIpObGQ(bp+16eM(lnsq~BR?;YZk5^TkZ zIs5KXrfmeV!>MuD-9osmUjKywHP1j`#Hnx;Zg{v|5};+pWDzIqaFo^BK&&b}>=JJ2^RSW$9HzX-J5)Hp1(^XNFG)I3*ng#7^>GG@+b zw&U0ihq0HxHgC7jDv6v6bd+-~RFd0WH&YrZxWI0%^g;FQ)uIf*8X;*ZC0`9Ju|-Uc ze8;&ueyWVAPX&Cp$ubV*o#k$NS16Dt65$q_Q0VC#n>J^lGryhZ!9067O2Wm%VKPDy z3+11^Jmdt*a(4#Xr|pEza<9~@L7Na2IFvzmY%{`roT)}@x4LOMw?a>+1v=tt)uUK@ z_FG$Hb7a0n1`&q<(UHc%+oJmZlBt=|>v0zE@O~X1KRz$2zKgkA z_fMBVclGwRZ9AqCq*0iT=(d4%30cF_K!Sr%BZHd$x0i9R7xm(5h!TVzSh|uNS8*%F zRSYM-MI#>vp8+=LKdS#IRC4y*=>S&ovn8C|*N9okySh#e&`s}k`}25P4(iyYTm#Tq zWZ>}HaI25O=NEWq2y(X(DRZHd-tE#79?!kLxMYrza|qL^35eFFHl=jkedG0`;k`>i zPTDo*tT7Uh)^yAutWWBNJyPtczQKgA>-@kq=36XF34lA~06+Mv#hfwf4S^%)oc@&B zJh!7eUC0#_FIrXcwQN^AMJR}D3FEzXh^4(RuL~W<98giYy68fsU>l%t5?EqW60qCc*xW$QCpPhfby>qisP`9^t3Za6C6CIQ?uiJ?Rgtg}dnU z`I9SheCiReOD5zKAAYkeNQ_|Eq-T6klkIIn&on|O&ch?E_E{~sHJ8Dt!-i#a3$^L+rx?<@VaWQ>Fey|zk=OyI1})RP?-A_7WCpYMu($>!mHAFt!yXOuKP zLu~cxvFtVZt`597(L&?UdE@jm zPNr0Qh5C6Odvz2cV}qy$$K#p~!mm3w9_5PS1xdu?Qc@RA{r*eg;)Dr=aMO5?zf|{KAh3_5Dz0Mx<<3p&%Bj7w(gD6A zIBhkb>3bEg2=%_Ndu2rjVYG`P@2LCSjWMa`(${iTqVPPBevw7rqs#OkK1w1uYmUE_ zihAO+Xw*rvtz7+(akmBa=W0@xaj(P_7}>GYe-7neu$FvS?u;{G`QRS6=|`0G`IhD4 zlSp)>3@u5N<_N)nMB|cwwW#xID$u&0848hl-@uw{d*tT}dfiA+m=fM^_0c8vo?#c9E{N}dyu(Ouv7Pg9?ewT>ljf1PlA(5~;WE=H7=&epuauyx<}od^Yn5;*RP zWc8#e$=JeV#T(*-Z4ha?zrliQP#~H&NJ0{}yr~7YV^GQ^TCJ*!_KxcMA~6NFoUbA< zzAq+U8~fe;atMf$!NTs~6Lp%@|2ApmeCgJbl`Kf)_5N*$e}_kJ&*&W%`E!C1Lg2zh zg*nx#@1;ENiKj;bb`$gNmGC)o61K?A)MJT50*-YEJxcCeuzz*_24V0kHy?HpNOAEb zq*cU59`9RfPv{zQR~gXn`2BOUMRPHwIeSq_;%>s%sLPl(PB^{t!9eio==%Y}Oxc!j zU*Ch9aj?5Ndo#!9XR3BFZx^0cpH9Yv=#R|Gx>6?BpdP;eJzql7JIZ6M>Kd0v3e$)h z=_JcY!AOmZGw9d@s}WwN;EA@n%>vv(a;k%~JZs;*Ohp~5IwCos;=ifors+P{G%)9&h)JIgu$MXLu#Y1^#Trw`kMTnT?w1L`T6!hN&d9Ijq zmjSlu9~(!Z;BV$!#qKSh53f@HVZA;@4n}WrV9&lPWvgisAsCRk(yh9y8d86|cqLxUSL;_X=hl%8pXh@TXwuV}?6V!t+ z=Rl#W#i?2NWE>M7cP!nW!s0=E$56rRj=?Ny6+0pnU7u+5w8+QHXn`BPVds~|$_-L3 z|FB4gJ~08d!0Svu2Ns+uLKLq@LBrP{lFQ%L4Ayc)q!m^1s$RAo0JyoJ@B7?BlOTbI zGGh!4``Zp$h$gQR1VQTpoulB%)fy?pY9yRETA2#_sL}sMKklhd4Z3h_e1j6BRfZ1e@@AYOo;C*SlVQ%I{vIQjb0 zriYnJr0nl*F6u+W5f4Oeat}Pb$00r{A0#ArJC*`F$3AAWySt#Y zUuy{09(@IJu({eP>dY<@&3HO8?4@Gz+rNHqF0O&Bkp zUpP*{7sWjDBOnAvVsD{U`rGmVFi`A8r_0Plm2Z)-nv#DqYn6N)Ee&$Pfz%{mi++F` zaTO;f(Nox+)Bz@-!mH|-N*H9lY2oU9E_SB3G(S9V(0q62i3PHJ8dkFAEIK{rz^$V@ zHAe61hHRv_C6D|-#6rSC_?qDphhU*NHgaF!&-Kuaxdt=ApV| zM8tHBfOQKm+1`-Jrft#|V8=!mg-}v+hHhR{Jh=mlX1;<6!9st z2se2`q6eE>uKohN?D^A~81WzRUo3BeG9-=kn!k^@=!($$U|lLB7Bto>qj_ zxOT-cvC^VYQd7(#aJ3d@oM)%w*3eZu)UO#BE+5d4rLkzpP~TWF82#T)+W&)DoirMI z0@9R?FqBBV5sD9S;(mXDLD;2^ojpLtYCK*Uy%*DF7jGMwz4xp#9kNm2>FQsuS{#Di zhQ2fwDXO39w$mrx?kp94+C=)J zT|sCYS`znRol8W~Xp5Nm$HnQgez3@09n!0?n{CsHVj&yBJ$^w{lSGHAggtTD+`uvy zxx_v)RSMDSOR+!Ogku_Uzi2X_{v^&VW$doKLD$8ar&0Gw&Q&(Icz%L?i?VTD+%u_3gPA6nuG$H}We7?a1Cf%u>cyGj7-J+AI{ir;;VL_e)hNfkH0 z)CC>B_}80^i45cRXiG)PB4`DB@prVdZ**DQrNS6U*$emeMQQj4ODty@wvmkecywBo zL~MBjD+EN6SL5?u_iVZ-d(E|)v()0RkB4@*UM}d!w|C7 z?fsTbXkT?WHK%aroQ2?<|(y209z~^Xf-_tEqOoxhK>RIx66)r_7gM#s6Z&9 zcIS<_r4lD2^Uc&o9B|H(H9A_0V>IAfDd?*uTXKh*iaY~E*}sA5qY?tV4;|ZsWO3*b z;IlQTjpr(?*aNzTqx)DA)QPJ}x*L=uMjc^7+u#$n@t?Z^PfOM}1?W=}&vI>3JQ+SLJNo ziv!<@QTRS}S}MA_mgMMZ?wV)AWF}RYrVsRAXec<6qqdujnuRvR(M&lU{TKhR{sV2C zoReYgQ+t@dX|CugYo7gwq|?baM6K06{Vb`uO;Df!PR{-@RN6Qk`#k5}e7_!s4w0GW z(=4*m8xLP59cp+HRw!}^d|b#mj<>nhgV$%__-^~&!?wu~p73PxXPo@k`4sYWu`tm> z2RJ8PA4-h&Xz%JlEOz;*E`e1g=7HGsCkfvC;+1U2uD=osL9$B%s}3GL6D%<{thjPR zMVTpZbq7BEpy=6FpSv5of^)ps4mY5SH1-Er`%L>t)1j)2+wE7Xx^Bjft$b>n#bhAo zlaQK8(F}8<)V)$%m;AHma@G>bn}q+cnv$DFI5+&##p~S4l&YfG6%4 zMAS}^n)h`3u5D5iW}D6To4vmI#6%n90dr&VD+uje*fW)RX(Kqc)u5hkW7axYKdkyy z9Z-rdj)GVb0xxjf1#M(hRKw=yMIj)JIG7N^}*`QGASi z?K!KTo!r&eF*Y_vd%Bb6^d|7&8+Ze<*Mpw>nV^r_3N z&v}8v+V7L6Z##+3<%CqIW7k{3&{>t3ANZT-pqs}oJ4eQYp!nqQ0QM?j*cAn#NcEOu3*4->g!!nq=3vs4wx zDAl_@oG&fq{6To>#4a}UwEP+x2ymY}TW_oFhVGSPex_2KLZG>29>X6=s4NvavD5Jc zQ_*e}$HAoPqTAE2g%@26ei}Z^YWcWWR)--JfCLBa0g-Hi zAQzojZSnzfoIvqWKSCd=q43=$WMJgQz4hBOZnifO0aG}shepi-#lw}H1vwut zC1LO>XePgl^?}aMHtH#x6limj9AW%T!o46Ysd17vpkdXb*I+fRu9ojc$Y$oqwUYRW zDTWz4z}Dbf)0cD2l#V|427Q&*q#>>`Ca@ks+kxRSIIf$8xt8T+DpALMvqyjG5UFn$ zWuKsE``f84Vl0K)ZeQr&q7CQ7x1>O|YEW%3U;B;jo`S*t>wJ43TUc#>2wE1%#MU79 zDM1y&A|BrI^{_PcSZ5Us0zXsDnhMQOk1G0XU*7%`Ioblr^!a9=fV(yCl@f%gnGxG; z-pmCs4^trWCAxkan2)#ok(j>e-sGiVnf{Ji=Z>2g5lh&M9u;R3J_)uK$gFF-(&~pi zqk*1Z^HbGP(q4N&=$zeJcoTD!sntpDeHjqm&CY{FMIMT_iV0VUgu<)H02NVv^_LB} zIppmed`jVr^=l~r!05XXC0?d#k%NU*wD&(Ow+X(1l$QOqnfatAPMmSyMk%ZkW6cG3 z)NRU?1hvH=D>uUdnK|%?q0|&Qs*|YKA1`PEzueA*rdN7;c8N-KUA>m&8RrI9GDvn$ z7yG@2KUW9hnB%!YREEAsM>Cr1Tco$@Hin=+tHn>x2Jp2hrE_g)Jeqm^G&9mktvnrV zU^5* zjM9c@Y056>E#Gs(o9Sj87948y_R3Us0Cih?p$Qs0V5H1-d%vCi`5pl{bs<64FzT}` zr2Cy$pLCzy(#d+0ejU`#(=H{9M?}0MUGUe?C?;-R6Ib#q*DnT$ZE-V|$iv-epl?Ov zsZ(shg-@K{YoPxIPd@e>d%PUzP6SEWq*JlAOdJpDdP~h){j2U0Jf_#Y)_0R90qPD7W zLm`FSpUKv8(}}OTMl{o&C_d9NnxjZlo%Pd6a%kSUI;x#>bv4A7vz7{#khyWX(H9a^ zZ56oh<%Z*)Wqas4kXG`(ON)Q9$A$N^H8nTMp0kGPXAk%X zJ)v$QrQ0kty9QyNO3j+TUmg=}zp;0wnL!F8{f9*dQsOTq=zmk|`FG(-`&SXi5fS}- zYL=cv7;!C!x8xXY4CSw!hUa{0?nOEs@@(m{M$Ukos_sgYjwS>-M(-Z^h9(M9BA5Mk zDJ?Ug1H&V=Nm^3+=HjJ=MT<#aZ3r58ynd zkD|#2r1~{f+^(eHKaHBYIdfWl-JRZKl2Z~` z#`MpHyN2~pSSUm%^}CDH|Wwts({xR2`%CMBCx%_rbn%=DbEZnO_{XLsRw+S>_@i10dl0)Kog_o6 zBJv_5mwNGT9g39_dt2sak36lpHm<85lXp@{9~)Wv;5DTMh)0P;rJ!oiGp)EAbE!hV zKcvix1dtN9I+U$GK4@EbWBFM9ie5;nik&Bc&sIh8DIxZTDy zf{tSq_1TnM^J`JVg6_XAF*Iu0;Fp`ZNCOoO3fF5WAGwS$O3Zw|#nmiT+_TUoz0VfB zyEb8ng6C~#hQb0{loRMKLw$-A{BtLg%C^i;+MS+Iiu$(5QoV?02e|bFS90WTK z;_sx?KuYMrCFXw`RhB6hmt_3^2HH}l1OI&^-F!Vb4MYXPk(dX&`k5E0MK z{jGi~BVXrEBc7O8unyhOw?4eD5bOfTt-(GH1SGT6?j2 zYFw-pC&oeal6wCc1uyvMa3vfmt5;2ONE?om6?D<{q@CeqkIze?9olO*7x#FM(5fW+ z>Rr4=LyN^qSCQ06McKrPb#odIiQD_VsZ?%ow4w3_7*m^sDphqb8&8RoHyod`WR`n$ z@c&`=ASpS3f@D3hC}@w8KdhZJZTK)BB)?4~VIM;XBMCvzIL2M^4~!2?V#zK&t$sMs z3iLmNl}=S!z8h|L5c;|ct*OhhFCi&76rwNwm2o0IM3!tsk$LqQ>gkC)`oOeE|0~1C zxgwdqW5foE{1DOo)7In)Xc!?HoQ-f%`Z>(jG*&l^yMMR2_P)olWzF(t!@0x6QjpLP zrO*(m^Yx%H5u6z0>=Jh9n@IfS%FoXm3bbEI1p+T^ES0)Z%84HZG;5+M$fuK$a&w+d>r4cm6pLQ8?7MT*m+K?^Nz#YymB1%efKf)+2*QXE3? z-~{&)tVm07ElzNEcYhb(`sbfnYxCPrW-`x4p6kA^^E?i|Z?C=;vQgnUAgB7*;fS=3 zSTJyEKIzgqBAO;gIKXoI`vAVMhb^HSkVq<6L0v1Me{Ac$_CuNz6f%9yL~gTb`yYU| z$#d2I%dbM_Y8Q_I9O9*R&FRwdi<{3mS5y~?`h%xCGauy6X3kqyEc)fDX;oOdHP8q| z!g$@MTWgJN_#esg@~9l5^tueYz_C5Y!E-(L=*5rR2mbnoNODg+zABaWVt{^A|- zg6O8!&$zfY=RLD*Gw_7ST9Jkt=Yr74=*CN0<<^&BU;}p|HjcoBT>Zyi#d6&#k$aOZdYs#a|XoQqrcMd1of%2FXVQT(Rp-x$AO-RVd>PU z7vp`DkUY=LC3^PecW!O5TofB()h9nOc!jQWa=BuGj;q^Wwv#RAPtTy~Qlsk!)d>nt zTUBn^*Hk-V6Qe3cS|Nz9c6UX=At%Z<*b$`(79$oss>O=JN(a7^p8X@L_FAFEwb$xC zMsIB{LW^b7X-mjz|D5Loha8Z)J*DDrq?(x+8MJibB#S3ce}>-dPyU>-j4iJ^`^J>` z45az{?N0=pg~`b!A(T2+t4~W~J(mej12X-^n;wg~&_9UDxy|mxZ8O-P?p+9<+ZX-7 zpuomYPqaB5(1~TF*-3qBA0Y~EA@w&pQ}Hh`ZuU_#G)vogE^wZWP zuFFzkuf4SJd1d%lwCBufX{GK{UsJnXCu+7{=&`e-4_jBo#e4R5<>@pt!^xUs1b3gB z5zeR*V&SUzBsrYa{jd5gG=oernOb_2cDntygp1nkqwf1tH+khTexsg3Rc1IToA4c~ z+^Oh5@BXYDLB7?y_%r9>m2g3eh@VgAyXMvRB7Sd$z)Hg=)%)AVfvJ&qTU(vHiasJG zt!mSB%HmrFioCpIDJTO}u62B&9}N|c}? zz*N$UK0JRe_{TdCO^QP7+Zq=j16%&2L}u*GTpZ~%oj0EP-f8Y@PJ#7UaPR3FL6BG$+M0Egg$x?R!duyH`)OlGG(=;DdB|{I@3wRxlzWN_((XN(*Pqp5 z#ztmj$Xocy68%=0KVe|!RkfafsQ}9sydahXP8+qEBnHL-I3v%B;uId$u;mviF%4dh zAT`CYz;)>H-p{R#a;qg@$Q&KklWs(_znUFJf`rJ5wE6?t|BxB5b|!|f<%!e}?7%4YC37GBexX=Kp@{X_;p7m|mDA+erPDU#2w;TR?{W&Kk1{j%iFJdk3**lAJCRkkYZpC6u!sbn=DRJF9#NZFcFn>+b+08^{7CRu2 zPU#PpWNxbz>)O_h@R<`8zc>+okKRz#qfE2K3OdU03QB1nY2c(nMJ(5|*9qGi6pSB8 z1<;aYL1XLu?H#nP=JQ0l;ROMzwrWqMN-TF@a9wT3TbZ!i+A!vPc|;`^_?5iA81%<( zPJTuep!O^>vGPxahZF%?GO4cq?Y>3&^Y^=u*B%!U8a1L{E5ZO%7H;O5xdTWR`X2L~ z9*m_dlNd=W(PVi*UwYxU$2Z)Rk%Uuh!J*c{`#p|zTafJuMZfps8Rs_}mhko#Uv~nw z)>WXuQyt$CNg1EZ?KHzC;nZBs)TyF>fK8b>q(Mh>$_UR4%kKWn+1-C~;uq6% zTuy@@K4&;aT1)moqdt*zRbQ^uo;T>>1Q-`Yh$wQzYIuilEYcPVmwfL2Fez6Nj!1+# z|BM!9`~9nJKUz1PODv$;l@a=`JcLKE!jx7$JhtPx;;wOFLgv*%jDtpLc^X@!xM=Iq zutvqAf9)@O4~vHH<1z_-K4u@|d}CT-Va5e7M+O;6AMc<3?1cn-OKl>KbM)o-Y@J(YkVZ`h-68mZ4{*(GR&xAZ2xxGmz;L`Tc?@snzIEP0Dl4iPcskIsgn_Ksm4qjPI^%j_GmsM$TaJ7L;84@^Qkju zsOQ2pl@%Ib>#0v5q$nnl-&>qD+LKX%jR_4Z(fpGg>`@d5@dm#FwedM6J%B7 zO^u8Zo>sV6(42OEf;Koew7A`Jesz;1GVCw72_?}6ZZ-!;)H~d`e2c?n@9nbdVSs!S zM!8;)dum_6Z_MMrd3ymyBt``CW`(Sm5u*J=H9KB-GS#st*(ehmLj{A*%F0P^p1vUe z25H3MDlD8+Ci$H4P$!AY(MgmAtXyEcU2g9^mOMSS+{Y0|N9fv=n-4TxDzf&onACrR z+gT8)08u%-=j}>Q4EvstF+NqK$zA05q(HaAmbW2S#GClV$zeiF3LBmM2E8QYhG~3V z*_u^)QflPyHoW5xqbGlV1E5lYL-h7!B#AtT^(@Br= zwQ$U0{p-2V3W^eLKaNW#g#piH{<1<@|oHi>lO&I;TzdI-a7Ppsa3_&-5x(hZc zY58K{Zw704SugIwUSEHsVt3A^P-my=ovB-ak7UeZEIpIv+YKXCJXh-~+h=6~ctf1w z+!&{thDb-)cr80oM?x@xTyA0U+Ye{`Mbw!dO-hDAjZx>^k|N){7ZkUr#eW=^Jal~6 zRq0Wm&{$_z{yd#BoPR*_C_dc3=j;f~?Gx3iHQ-TJ!Q8P=@l|Ndg#eosaK*FPjz|NO z+>CK{=!wq84+F2?+x97RjT(4|j}A0^Yny+RN&sLXS?3k6y-6ciMn+CR9PjHT)VQih z{H$oICYZl#hXaBisn%58+F3&_I_!^}5!Qr=8nZwBfOuE=p@-y9K?7cv@j67x@<&4G zYBrw8tyQTI%!%#gd}T4(@pKJ5O3CRih(G{;BZSFZR(ygbVhB|9xZf6+=A|}7lIoP` z%!fztWPe4lv(v_`w5~ozGS;tF6L~%U1N0^*l8Zl{l$=!fi-*{-^C~t`{`huIBTZ1v z@F++al4dpgvMebKq138abTkKHM<|nZRgN|@tT+NR|YYvi$K1viD{E-V^Cq9YKy$vOVdLAm%z3#v? z>qL17$aqs$8opE*OT;cLm`F?WVeRjk0k54m&(YYfOAkq!)>f$8Sff7QMZuEs7gsT2 zrDyuz<1p*T5M9yR$$pNv{kD!*HjH0ETR97lX0clHNM+4-d1bo9m0=&e(R|Lrqf(SP zJJ3^K^l^%O-U>`vKF{d!5+mBD4C1hoCB&w^z#9tWGgfmZLR4^V#~2vOX@xHmPwo2# z+PSIl*;poi6P(3L1vCB!ppuH*j?%qqR+4tMWJ#NT$_qV{KQHi_kW zV_v_@R|M;7#1Yrmb^RtdjvasW0(F8MemcoJK3~Xa+=cG~g92g_wIgkavuiN1X*Sbgj@8+{0QRAAS)HEoj% zsp2+a`C~&ofzk`BdXFyV4n4NW<*WrFm*;&rMHO7F%n8lD3L`yj10FhgM*7dwt(J<9 z^&H)w_HVn8#rXj2hiwZL7JJLTTpwNAt?UO08T$VboP`skP?P^ClDhQY+`AQM zhhOcCfV$yQk_RwLn_dO#^{dW$^&jnIe*B(u0kVN+#%BgS6){4vk(ih{5jzhxadY+q z1Y(V$?XkxutMW4r%PC+N|Kni{x+Z$B_(=4zLP`GQW>Jie%-)^iY^ zp&fa$|8KuKLz#rk4~IB938JPGe>ObRfV6j*+>6_ZX5WjnNDWPRvzDK9dIgJp%<%QQ z>!;PpkQ9_lzPH1N-!7U;*gMblorUw1jBl)F=l1mQa(B3qoejN^D%a&J{^zWaJU*CI z5rZ=Fe2~clLj7N-{ht26R*wJGc>4bvWy@bZG}$Y8Li}lB!^-3InH?TyQ(nb^>wv-1 z?0lKXu1~S5z>k)=+`<(<+&&Ynr_G+@V*d&;6yQ4FtO=UK#8wv;M$>4tT;kxC?S zt|NM)0O2hK>8=IzsYd&_1?He}7Q}#Z1T%0_4QzJe0`BF#H$mk*NV_1{73K^|E8ru4 z8T>wVY`#)cklYkzx>pDYqqpg0WA#2D5d0CHN~kYD#(GFG zVTQZr!=KQXH~!2w>#RH-61mb>E|KeH(+D-@{R3yIrFWDM%{~EgusO{JC7>Z1G5O)D zXO7R!erKV|2j_zG?G^eUVGH1z)sIo9MQhd-_x7=VSqw9dC3={q1`vamEw{&W`mlO2 z*nLCaYvi&tuBA7XaYyX@HzL0MjQT;?V3&qpmJxN=*ho$5+r1f1t!+-rbmQOG^U@Rs z#H)34cRez?BEyIWQbFe1lc=B=zgL+et|1@Nq7s$Xog-pMw||N2ZrJqGO!kcYb$r8= zDm{4}NcuBN&|AT+QEV;k?9QRaso-D;S_Oh?4jp|M%2fdpb%jVIfu9<&%Z!r2r2#il zUjwrB3c2EH(?zr`w{n^0%LnTQQhw6>7;S78(x}a2&D-TJtnmyd%v!db)da`Pk%sAR zZRn+Bs;jKBxz($!R43VVIy807jvy3qonhH3PTO?v=xj>k!{%h5y6@pn#G<0ii%XjS zp*!kveYwAQ{GB}ic1>ZA{8JFO!~#KDcR-%s6(%z-Wi-VaARC2wG%>`n+!FNYwio32 zS3#nGoSM@^&v%y+Dq)`^9Y-~6Mm;+JgXg+VeFXL&YoLn9pD(KNPh+tLoYXaz} zuNawedPEuXNq)kB4_o17oxONXa8r%>Gd8(Z-6NlFtA7-~kjlS!hV?(C{L|3Dd;&?& z9!~8?bTh;Y38v;(R|rabJP-ecw*4lN!mEfTb7hq+0?J18Vh1Y_y7>4|&xn{ig7yYG z<4cn=<=k;}1QLmnQ~T(;&?JAHb@yYS04BAiqgTT|?bS*d@E~kVR%@7|5}sV>d95 zNHH5nki;dlu2zoLCg{qjG#FB8yuq1E%eDCD1?<#!2(g^`pi{D&PuF~R3L_^7O=T2? zgMR?LLA}gtj!@D;VfAnN|FTgu0=I6ObWV@jY|hu%=j0Q;sUP&!Xdg^tv?s$cx{*@2 zvO{rd6N1|1)R4(+xROM*S}%W$S|Y!CB#&%NOW&)Zm2hD!fIr}AaTgFGU*3|bdpp#K zh$=eo)Mrji+`E`nFDhrl(^T_zo5>mUG>qiU`EA8z6WVj1m8*|AK3il*rZB-IX%VLHj51Gfb`R|+t%xVm4IU|BJToGQNgo%Uk{RZe zL;*R5jVB_xv|yFQZf>qiJ`;#^IWhxHiFbL^2@0UYP6*;@PZwXj&NIc8e4+Kjg<^}O zoM*ttqSJgF6vH!C+dRSw>{DNLI7p0@g-R+$6TKC8WgN9ub!oRyg{;}nr*FJzdmT9Z z*9J}zCu)xEe|&RjLa=`2cFfjUs-BnkOl-};zQlc~p@F4H2*$A>0wrd+Qz;70MZSv3 zt9Wdz(*~%h+YEEKB-l(h3CfRe7pM7%4Jt;#ll5HU-X%Y7zXaQEz1V~g_c*JC*Ayib zz~L6;jfECM44Q&TbWt*R*~r=*A|Ap`CWrlqp#@e;Vc`R=jsE~Yj1&tucW_ns!^{!+ zgzlUv+{U*aU7~^FQ*#d?-(jIYB~ynJ=T^zLHf{M<5uyd-PwT}pcDEccb4?gp$as5r z&!Fx-g=HhlIuNW2DjlK277XPTZyfx{F6xc@*P5K}Ddy+EN@7e#F@|k=xLp3@e#k;m zFHeY_{xtHUgq120EpcMwU%&bmOed|xd>!X6T{37q#>zV;iME2D+QIS@--y8#!8Py; zS#GuyhPPEHLUa_$=+&ZSt!E#!PlzeIY*TPWo_TL(j$>)yUOym2@cd=9IX<3A#5*X} z7LIe#84GTQQSuBuybArD|Cr3$JYS4a^_CD%NU2_a&7dNz#)W6STh4S&e=;Pka7B6D?S4cL2Jgg0IQta5Cs9ofm4*u_Rw89#le z^T0s z(W649K7E574}^_1`$*>nBO4yRY}HzICgJ#$_gqXSyhFpp_ETCN`|WZ6=n|*ZK9hg!OzF6e&BJF8i(QMQ++G{ zG>{(H`)TbYbw+7e8ok^fKU2ZLKojBnz{#eSdMk&9SiWw@=-GL;R8%mr52r+%LBxEV zq6ciFS=8S<@IOHOCrdV}&@zIE<**dXVrbr9NFT(NQ0Wg7155|a87{Dwiy|*7I%i`= z*~>9-e9R`p8P6}520jC`0SF7e0$K2Y8bA$U#`EW2um2YU46MpipaRZ^U+?Z$x4 zoQ&yEYNFFv0qFApilXbRcf*To6@vB8(BG#Jgr8lWL!R50_CX8w>ch%3E3a$Jf6vR@ z|B5nj?EJ9b2jQ``&ChdLK~!i+hL)aJvT^a!NGM6wNNGO233zPVMk=c#hM2|dZL8*7 zKOQd_KP4rC5}K;Lb0Ob0X654Lf{SemkXvtt5j-$H(s|51T59rGZ(ZQU5imgLI+z2Z zq^_B8UTMzrnw|MZcv-|y>Lb^k@$!EFJcltfL7y*2fEJ5#%*;t46tHAozag|^-{XRu zXQ~+2`DyQBqBGsF`1i$>;)-CA8(D1uM-YI86Y^ZK0#ey8fLuB5kL0E7)%QR(2<4VF z<+>M5{y1gsQT$#%o*7`Q_3r}Pl&Gjvr?-XQmRfejc^L;ZCqUi?o&7K_B7>#IV~N7& z3hRSlS<>dwn8JySHLH6okoueCUAO#*SMv-RchX}%72V~nexEG-^3+&1=3#IIXUf+{ z%o?%ZFCUVbmOaSKpxI6QHLXSuF&+)q~SfSOEE{+f9(2nakff-ycThBtqW|Ei5k z=lXt3#Ip0Ht(B3x0V$#adsY5U?U-%(;ws&4>2G7s+LaXV8>-iMU9KT;SKJ}r%vn9& zv#ZlW=B=@{B#93yQs@2u0gNj(n7iu~s!j5mW{C!6>I^ZnIR7kO(ypGB6|UZKI*oWF zq_&~M@O8SB?WwgoqV2pPuihH{{DuqbrQ)|=|19!JbW4@)zjh_Q{MT~WRt#7G)hokL>qB;O-O|o+%GM+ z-@x{m+T4%$Cfu$^YK#6!eEDMEQ`qXXaEx?Xi>$au&D0IZO#1W(Gbw~GbG6>yZ^$6t zn7r0)p=E;POJlwk72N%ys0Qq!2D`?JR}H=BnvDy*8}>QuB>E1`9D9doEZI&w9~6MC z5H$W;`*c{KZ7pf=IaTv0)Ao(90YItSFC^=1ODjgGV+dL2w1DeJy|5Q7`xJijnc26qo4&6hm?iws{!gS?(jnB1 zWcs`dN3{uW=h4{x8Tm^=D>B5E#(a4<*tYo-ealY2Z)Hy{5j|aeCladr0*J@B#Dr6! z_RujU>CkMc;h!c$Q66tBYT(gTP@^z;sVAxMXSIad;Rnc;IBB{^Mzc;U#*}cgPgm@G+C0zJeAQJTmb@W> zH;Q_4isj-J>04^24+`mOq+_NRLxMw(>KK=2o@QND?cfV@5s_YEe^B-z#h^l|c1om5 zr*|47z20|zJaxabn?3tnDl_((_Xuit6WO}qiJp4>e@Tv~%Yxb8*O+UeYTf?z+nJeY zJ@yqRb=w3r?Uvk&{&rQ{K-+cMu>|IvvTsc@{81sn@Bbk~^oIr6+vfCT)JN#!O%t5m zg(Tlcam!jX1tTYqda_jV^W?{Uwb8T8XaeP<3&;%4@hU@qxh)$_ovx6=6Vp?A3nXFd zxGjmpEl_%E8fSnI4>mg)H^yoxS3vaKV|$!u%OEM^$$T4V;)8T4Z?gdF<(u}(R8@rPCT^8yTBxprzv8OD z`@>XRHfNi(W*|2%M8jF}npBUh3H}Y?1$xbN!Wu)8d>~gWFtRkC8MgvKyDd4`nUj;! z@UB*^hNK#@E!4V4a9XlqfH07rQ%cc8X9Ra#u)IzSX=JD1zo;<0_9U-$y0Equ8RuME zPxCBqPBGdiY9AD>xSfFNn{3I#rEED0U@~`+gyAeR{k{=SOAtZS^+$jX7lQ^kK5BC` zuev54wE0FBTf0_1xg@l1wRRa7=;H0-_UUAvBG;{5HBcyQCRe;Dh*LSM$s^I-05s>z za8}{WhAkfD^q!mk%$=fa*}_P-@BDj28lvif90*?`?DBdh#|@k#^1qZ!JQ?oJij7zB zRmVW#u73JxNjibNQ;UG%7W8V$7C1CC8_0>}ByT-ML#xM|xFYbt$}RP$Gf6yP#Nsw8 zF6T8VZ)bO)IWbme==y?#c>-O1*S!R6vhipE;?lboO)Fc0;)As`{}?RS3=%IfUL%q< z@xPI?j>PY}VQ;;LX4y>gbJtkRjgf>VHtU4ud*~H#V%Bo%Jax`Y>>QtXk2!sqA6+<8 zgsO|mj9rBl2`E{1r$VW$sbp)-vS*M<*OmoID>rfRqh&J@b)+@u_8IOI6>E}jF=wHO z)n4KWQLZdmSfASlxl<2!ie-HULAeh&np7tfd_lX3{sFso$ z{5ERwm^=M8sJ$A4mxsRNrpJ5DPxwIi$D(#3|y zF?a5}mo1(&%lxf>X&Bp%FuL3Ehw2H~K%z42^otiu@zje!vEDY0iQvpIVS(W_@BLL+ zcj2`tYNgM4?@ZOb@-+(6YE+*Fd#;@QrtsBQQo>FDBY8h#6H<{`#N}OP1rZZ(>;t`^ z@zAovpi!A6G@jdx6emJ=C;aZ0=_4XEZ`FI`_~_2j-J7Avv_G-9{Dfb58Hb3gI=#_I z=k2YlIVUWX_lw{~FLe_=z z%xD!sy~ldGJ9gLCSzEBi^y~F@-zC8NF&DlB;{XN*dfFKO-izVf6BeKu$c{7L{u|WT zORYPcl!I*6RykIzPP+!c=*2eELW7jNOFeBQ)34;!J?lTDF8GE4T8z_FL^?OfX$7mxTp|idOUFTy7;(QMq#(b_@GY09)E4M)1E=S^4 zhj;%hFKHYKIjER73q0A}78+pJ@v~MZU1#w{&Xa8AdV0&E!{1Li*EEKF^!(VUDilA| zZe`lE0N<|K_^0ewXzhR-4P;p?WvPT`XPTXPV4)*6oEP3BccR|}-n^%QnDFj(Y4A|}?PMc|H4@;TPe@nI{+OKY=pO8LktSTc!R#wIv;%6gnfncLIzrDq~ z4==Y(cpYS620Oo2cc1+&eq!=M25-5jC{jV(GVE|+oHr69C; zy1UR+z3k>!G^ABd@7}Vgdi*yGUM2)A`#6Q`MchA#o%0_+O~>bgsS^5>aHc`ID-9WF ztE?3*IpjWGM-zi+8AL-<_zD&D9XnoS+)E!2Y1mJOj<5FdDvGI!T1JX!S;`%74Cj() zCLu09(rapOp~-0-RSrBm70q)oazK3vb|QQwU2l1aT;4K3sBxhPw3*1#whgBELQwda z`x*ZLI(8y-5%VfCZLrQL=0{?v-ngak_ z{I1lfL!lNKEniGtvR~HxPahJlp>FJWS)w4WFJ#p^PKr3oXR&>u1;S-~>1@bNZe6g+ zeH+OW9rJe=oG;6Flc=oIX=#opwGG86n_qmkNB*B{`X?g)yA;XeH9bAXtb3AlhOEZ_ znXEezw&~J&@zbw2WDr8aC)58J{$Hx{Gn=f3cWGk`2SCZ_?!Rb60|p0YrnR#D%x@~i zO2FW+XjN183tXz<{{YncCwlYokH>|5CQCn{L2Apf&*WY0uM@#>5s}T;%oO9H@R=G3 z${zn?W4*YmRgb-M*nxZ@oxno&MDiEU{hLMi+C?!jh5c*#&P?*w^)=aUj>F}MHPO@3$8BZ zA-#4yNEGbwBH{@7rsxE{rMujYm?Fy?4(4RuO%Npdt4M!94cpqUSX(cdr{;_jKUut= z1+9ZNaG4z9Dl$YjTg=v$7uRd93Y;8?j{8q^i<9s_1d-RR;dJ(%<(E&k2fbm;xS(&H z-my=-8gzPu^!q5P9~H(-w!YtH*%9=f{o0ZH$DxR;vF}ylOD8R4Ojf%;XWExJI>|w@ zMn_V5pv|se$;b(V4^Bi!PX|jYBoS-M!AWYSmgpiKK2N}k$GcWD_PbbU}Fz-P2SW#n?)ZCYgBK2g&lkx;?xl(7_t{VrP`@Uu}~^jU1@Cb6&^9aOC0V;J=-d~I7bP()=a9vz`HL&uX| z9Hz+@-fh^L3A6s-Ngr>dXsOy!f-;Oq+0Z#Hv};^XFqe{?swVMG**C-{9z?ym>)yUE z2_&N`s|W#uG3`FF+6rUT@TK#3Zo%)CO>>OBc;Ixr-^}M-Vhrb%Iia*mh}6wKs8OzB z-j&}Jnd2+wzhjZ#Z#Vxc|50o|ekX*zgw-J4c(@I1bZveQ>KimC7qF%IZhgo7B|((S z+7VI?GXYRa`h0p}>{}Seb^qgVUtjV3#UY&Q&TDIdmVD_$KR)nZQ(m|NU2j3JQ4H5- z@7XQT>C2een7>=%dyPy&LwtD!B(O1SJ(u0D1`J`23is(|KZ?uOKf6vVis)X8U={a1 zbh&|C}#%`z9gj1DsxeZ3Bce%6I(>JE3zUgZ2ZA2qMDY?wW4 z@Lpu2-4=^KyT!XnkspPK*Ik}-&X(0ws+DN!g>E94%>fTB95G;OR%D&wP8Eo;MxVRXXK=6D?uN>Zu{8e6Zbk|D2+QlTB2K16 z=-(&$+qzX2`=b_eFx6t{mYxc7qS#%#IW3WlWx_Pkldh-@&{gIgBUm<50NUITCzc6f z9G?gs@IzgNqyl0!wLA(y@&v^nUsa*9p`9jSgRSTKVvJ3M#YUwR2E&eV88LyBhEdDs84jag5}IXAzU#ouvKtjI&Amv#E@TlRi58<2RH@oR z#iK^^CL^AAdr_}e(Wh*`KLTz4PQN^R!^!*xQLGaAyQw}vmQF`I(i9_nkFY%C*gf{+BT&kUS zzItitMl^ATZGf|h8}6as?Vo242)kL(Ir-1%)6aSz`+VDaF(B5AxKW$CgGoQe^z6fg zeIZ2oc2tw0axWV`;G8~twcKBqmsKROTQM0%7w1(@B$rt>nf+{nA|aQ9Mz zr&xS=S!vFeaAuO^GlE1tyJkEpZxiSg`YaXx6g!N{qii1m7m;QFHy3}Ns?}AFXtTOn z{!1y=O}b?JVj#cWJDJv_dk!rAJQ#cmSNMB)qsJxgoIumRmui)1k!|*6y|B=w-Dgc^ zEsF%a4w+TbSkstWoqkL|kt?n0lj{ytv;NeM$^~5f7mraX{HwJmz7&@_fB-G`_x4_L-u0L zjQM|n^UJrzNk{|5cP>$sgtKvKJ|5k6^BbDM6@$jwxoMcL__Mbg^G47MnYA3hk{63? zVW~% zp21w)8Mib)M1Rzrb8tb0>RLD2PI9+_w8Wl4@2 zdlZMZ=Ak9|7nnApK?ae(=`^9Rhk!!Q$x`E1JMh-N|9fpI_KX1{VJ|>dXE5+tw-7H_ zodYz?V{?XUbOWo_FF#6sjQ|+TtAFGhyP1+OtXbpRoB*DeTXV26PZpE&m=QDQfVap9 zUI2IG!+7u**BtLklZ7l+_ymTW{x{N>|IcStDv)Z)F8|(rNOyT77eqcx);t#20<$jW zxSTzq8hZBe4f_8yOdsR*9G#f6d%L5({2L)0A~KQL-pbOW%#qW8&+n=CP`^g?`Ueq& zrs@WVCv7lwqDN{kW|81YwbLYF9RsvGTlg;lj?tfG9spr68#rK+t0 z#WnD`+&bKDM02=(2rb3CAKStVk8%evK8A6Q&MndMh(EtTDYHW*f-g4O$8-7uiHC?}$LW4_ z8g@r`BTMBhoWJ=#mZJ&hK3Cb`zi(R9{2jBtGK1!Gtn1=X91t!T&-8Quy&=;3@MhjSIZBE zqCS#EzvN<12b=0sRcgp)xdGyxwE2k^oKueod6+l7jO#LGp5K>qhjcr9&!SYX(8sR8 zUd|bA^=K`Mr#^lFfjEd$QS=MeuPPw7EgEv3h-oh=EM3f+ruylv)b<+T{gp7y3 zK3$N`&dwyTZkniA#NFo!AD;;~&j|sNSx<)k5<`yrRp%m-^-~80#cinYv3yH9SgqF1 zpYo`wbP6EATISzdb#AutPW-cCRJNkfJ0@YVe3C`U#4)KiTqRQL??26k1oS*op^0$5 zooZBF=Y6}w(YF%2c98kz4%}8aRctc$Ah5D% z{o{M;H!Gk%zUIeGHc3D7!;tAS#m)xt6L?KuZrS=`ScVbhqeRqK^kUH|!&*yH%t>^H zbXT4e1O(TR#|rvpG@TDy$H(4$sUWfvUO$mYVfbP4!^Sh(T=H-GB}%rY?qAeSsvd{2 zrW(;(SQXV{_oYs3JEUuqDB%q>6?hz8*}(Q2|9j)qF(Zz~%4!b36G<<_$rckM*Jkma z*gd~}p;TN>_}0+t14YpB?RV5aQz;b(^rmDUKnVjJHvY zwbl{({pFIT>5#KUf?hlS;eJ{bMMO*bk?;ZlhsA78HhTLA(m=JsWYD4!b{_5A5xX>u&FN&m%SYH)M>i`uL$k84r zk$JP?TC#5#iiZ?ti7(tzvtz&ew<1M-PTx9uyf1`NRt9SL7xiK@XB_?9tvHT3Qq7-=Iw1j(XDln165fh=2bUS#vqs2lY!iFIK#2eij)UEqhXBDQWe4*vf#M^ zaA(vt!Go*Ri`Fm+%47gFnd1Px0#ngG{PE|>>Y;jrS(=ckToP-(vtsO`(W2Kn+1z_Y zaS56MK}mInpFF4_ebo~pC8`a{hCId&EDMfRf>@(J*Vv18+A&Wg%_nOk>tqf1oJ8&R z6BRp_$AV${pi$s1$hKqZL&@T~;-h z?t$F0{IMUE_;}^3wl?`bEqLwbLzJO=bm=kWQFU=Et=4Cq3vE!e5j6*1RQZfc05h?d zWZ#z8S=l>pe1ZHX-UOQNpQ`Vvz`8i=M#Znm5n1?iG3b}o(irB_K(xAP@=+UPw#;jj zQUWZiR%?i_Gz{z!kxF#&4v;z*&U`nKejD5bzjU3fE*A|rD6ZP%<_5A@XT?STbMacN zlaTxmKymjnWfP=jvgamTFZMl6XrplKVzWZ^Q-$CuduOkfDmjZ|QLJ=qUtQFu`>-PI zp{u+Reu+RKK~}QpJjd1@rOr2n7N*pH{6d?0>QMIwkBR7JH?`WBaQWJmT4(wv$MSB6 zCxP}{f@e$Q!-$hp>shCjrkd73*LOnX?M8VhTqhY^X?$$YGQzy{2Tn)APwoTddJdWC zmO~i2ZjBlj%CBmYEqo8>1;Qt3v1?@+@;^hI{A5!*_TQ6i_c_T;8l5)K;2L~?u_y7T zQpfCy|AWg~Z{Kqoomr=$QsYuXoH7R_}uz? z{@0EZTqx!c1oBK^o~m8tk1{4IvkfyQwM{q7hi&e&>ogfn;^_A4Ercvl;2@(7x8%h3 zxyG2N?sf?qYWm$8SXqr3s7eqdAymoKI~apku+xKpPyO^crcp9>znd3K&TUO`F6Sv9 zhvO{Lr$2aHm%)k}8v}DHW9h+=_;_!wMhe+X5wi;j)ErB^pYEBCMh740 zBxP<{804&ymypms(VF>=ks=b#uJ1{s-&643$itt1WXM_!IN$x^z4}KkH_#~EO;3D% zOt#%h=Vzj7QE93ymc_yQGZ87f6&J+MKFzH<8rQs!JDlWFp`nt zV(Yj`v(I5>Sw{;7&;PUlEyg`zPE8BxwSBg^ays?>E3|Nzven&1w{7jtV{cxksMWum zZ&?bL>IBAR&aS6bE(-ph0vWzmR9e2QwALfrwfgS&tz&E#W#rfNu!PZ%`1FY29;`2E@OHe^P5NL5_{1I^y9VT0MAIPPLB5K3@99e0S6Ed*>&O=HC z)kB&HCCAZ)Z$}Xw`i%7HDYDuWbMpJxViNXTXW5U5^ZL}Ur3`kufv^IXlcKRVGgC74 zCEQ;ns5s(!-{fY5Gnn+-)d~00&gI^UKG>+?k?u{127aAM));`#mvG4b1>zdqiJxz$ zT~vFMV?xbXA6lrF@1^)V`7Q9%@x!@Mz{1xqW}wF_x$zI@_~F#H7A23`4GUV% zJv$K|x@T`cqOBc6B&n`;o?!V{7)^a_BktK1CFx7HT4tU*F9pM89-Dv~ob0aoo<&^@IPl+X7B{%(Ipyr*}D6x}~1Z;hw^!sK)pKUrq8u8EN zq)t~Pw$7_WGRQw5>ok`A*;P26ur6QFObs|P#q?b+hZ4`HUT<7F5IKuJ_(H@Iabte1 z$7^Hv;pO@#`9c4SRNDVR=|~oRV~=}>yCtUa zfA%(y+a2=P!X8ov&0?H9(dfUI@9Ii-#993|lcJ_bWX3#VTt0Gr3n*xDe&ZiMyxf-e zu+ewrg*g{|S@N|HIjPhqK|v@4wV4ZK=IiC1Mn%wO4J4 zTCrocs67%}sg|~O5J3^t-deF|i`uofP$TxN8_uDoCqtdx@m&lm)0W02R087T?nYBqA=9^c-ht_4R3#!0OMs%n( z2@JXXq8qqq$Zmv;3muWBqUb*@YfrdjCq`Ql)zV_~#XUrbyT+?_YbaUlC2`_@-2%r+HzPgo zWMpEa2E>!0*QvF}W&DVmoaOBTf*RkAf*;@gHJX22A7ylVogd46!NbqIl|Z^9HK!l~ zHyU0SZ3B;qu6p$Yv4^3Nf(@I}CeiJ=$!V5JDG?dK6f#-c zueoxW8IrqcU7L(KoQI6vI&A+G9Q}6nUjJ^fve(dx(SROo3g}Vjw}UmA^cM*5^dtDC z-n78y7(6jtgXkik$Jm)%&;4Qj877WrJ(2!gEa?>tLUZ(y3`D4+s509U!o%53cY~>4 z?H&0$Tz}kQ$=@M(Ec!Q+<nkRD_-q-s-V_E`w1v`NXeo)yxb#J9U!r(}hZ3rh4IbU=w}3;+)$OZI%}AqW-b z%Po0nQ3E9`=b9$l>7-%0@5PrXwuplKN|1vC{!Pd*zxF zA3?yc?sP7XDW)qb8nbn(JS$`;@!7TDRxD%TEwjImcWR+pP1sD&}hDskg75)XNyx+kluQndOd>zAK0s7J9$0WNxhnI^63rF*{ zq$^(^a_1{BdCNzG#or|cU>3Lnmn-oI_VDxq9ARuv&#vJY{l)7Sb{LJH!Eghx&!DkNP zGiVg*H>7lBG|9E~!6A+NI6X0reL$R~%@=L$ zhfQ_1-BwytE%y|iof>5 zOGy$nT8j4lc;Dhu3Ch7H0<>GYt1-Uk@**pjh@RUP4p&=#NJ7SBklNB}TYqrc>JvFl zePf2yM=?@cx;ov8oeK@uN6T#~BGVg)3w&3^S@GzVqW+LMbvd<RNG~g0iy@LkH>(-twtOR^LsDK8F zVd}ePrez+4&Atn7}&K1zJi@N>S=?F-=J21bFCYh)2Hv2m+a3J=p4`gn0KXZ9!ROj7`o zC$gtRSyIFpxak8E3YbHuv-UdgUa$?BNB_#6U7jIEi~J zAT`0G*ZyVq?;-s;6WCrr;XXORr_)}Z)*Ia;`s09qNvS{E)>r$|pTlDBO!833xN;i- zKbfmZ2E(e*&U*BGqA-IJtwWDNA7yb41G-^eA+$vfk;1xDo$fpkYv1sb!mU#WNXhNo z@1!@c5EioUT-sHTu3qoJB$49K;Rq8(xIb$CI%cn8V9}%Zi+Ej%{Ya2A!PWvMv&yXP zc$p&=f{2PZn%6^3WkBMw1U-P=hEBIW;h9gBy58#3ljjZ&7Q4`I$)*7SiD>|_)bqaY zUMJgi`DR@bdFL7yj8v!3*pvfks^1M+ESS?wYpR&)5P~=(GQSdCP7bdN@njEa^B92)(D`$~DE2-$Krec$~MjcH&^Q$8(uu@TXW3SZ_A2ymYJ?uDBo z{-4eaW**c=zd_4gH&jA&UgV=67szeM13mUg_S((SMwI5KlA@s*kMFZw&wYbeo*la! zNzupAy54f!z@gPnWL>Z)a`3S~upfBP3N_su) zC4@d6{Lj+`mf%rCPAam$SIcqlp~*im!+0j<18JtDO2-r{5iVJ$lhm=ZenSxF~NP`M26NM#(n|;<$d&viKTm+cn&K4qvX1 zXXYaSeP80t+J;?>>HrY}cFwE!r(GqO4@a4rYETy|L`g40!}f>Q4Dy!v+9BbON!J{IMEWx^@FAGmvUX;{ek-FWUsU;_G+uayT;n#cLVP;4K`tOaT2 z>lEWLoyUfs_&(&wI80W1Lf`QudHW|6@zR$jt=87KV(DWh@KJ)V!g*nJFCebReC0N$ z@|%41Cu$3CLtbt9CxciJt_IRipGx6~mw;Bc^DfD7bmK@FObrujF5@#Aw7BH78NKG2 zts3ChPFDL&bVpEA38-csoNDe{iSBr$>Pl+3^-ry7{AOs{P>W+HiAOen$y_)~R?Nkt z=M(Njk9l;PcPW?6y1dK7=3Jv0|1k;jEk#Tq;}#Wj zH!^9q3nWnY>bq4b%}Zr?)o(V$+sm93kL5A0Y6p+z3xZ^+pkSaz#rxCEr;iO*8lSD* z?avPii{H%Ff6m*f%CBS?5?ch$TluIy9+fs^9eg=gDz>-BGs{%hG}X; z0(ks8YJSqL_JP(bH0DL_5B|1Z#f5w?J_sxs^`g3Q=1Y>3;oF{sgs1nG`x*hZg;V7o z%(y8vwh+MUX))erd>imJ7Y$TG+jSNhRi08oNb$mx{V*UgDds)VrlC33DylqR%#en@ zuAGKDMQriwPPPgVvL#xh9fj?LtSWVFvPYC0)(XdwOwKC_=nAxuL2^e(a%0IT1xj9? zvPe;axP11(S}-8(gFm<@JAaMw91#>o2=`u;&=n~J1?HIP=@gp!KmVyP8 z=++fD{vr|UDuE%4VJQZV>5vf6D{IB06L*aTf}W;H@O|6P=K@f@ael*BU}pU(C->6G z?#ztNe8qr5kgK2|BU*UZqdnIDlYM>%?N|R|mqUbK*Sp1WFt|`H(W=+CwSH#bFHdct3g>y^MUhLlUg|B&YsPD%s7TJ^0z_`^~w_ zO=Rl;czuUx?&4T5jaBt5CY&8|M zk%{4~)_NA?3${O}Y^~)&wAiF$zMV z7@8RE1S)WtuXseaHo2R z{qeCqBv3vICZ*9>wVGse(r}Cs+}ov*SL!G}7bY<0G-|2a9Y}7sf)MIPexSVAoZ?j4 zwSq+l0AWl=eD<}~h>R4Ko~3hYJKlBXvl%-;Nh@fZ#2jrTb+pt_2(Y;2r-Y;V@NBI$YkUZIq*~lcARr>zL)1o| z`-g==Y4wXv*F)hEArNR zzLQDbpd!2dlL0&bFD{f|V`)I`z>%4tgmz7av8WLg^46 z0&m&g*%>yA_H68S{gpH}YC2TlNz3VHZ;C#6F)%S+J>!@)Uzkd$rXscHxA5(1eEIjP zXL;@&jS>jN0=sWq#2Csy(hM`CirV=nSV1BV%{2i@VU;*`-P4MC|KS+eKlB&BBy)`x zui|WHVHPQT9B_RdkPn}g(&OL!F&BUmB+ZnI*ysl2%*C3yMRJg$Bisdi>W;6I>gq($ z@kVFe>y{1sJP=-;caD`+holy);ZM=wwlA*IUXpjq_z@(`?c+upa*`$WpY{HuHE+Sc zx`?sJoa3ymd}k;Tk<~p$=euBza3Mp;RYy`>hx=lqL>L-(U0TR{&p~m;31pW zWZuycwK%%d?H!1lOE;NZ22%t79x5s6$=_cHoZ|2S8GEqRmVXuReoDiDO3eJyG*(q1 zByLZ3N3}N=Hh@G)?7j>VT;H#GDF>`R=6CKjv5_^B1?5z(bsC|ffeya~xK_r)#+>I+ zE)w9y&oXodvqhSmVZ^TT{KIF4ZfrRA@Ny%R!PiV91mHE7d+@ec=l3N#z=3BzVOlTB zD300Vdxz#+Ml2zmLSPK=ZKt}F>AY09Pa(!OG}Ua9TQyH!8Mxho_{r2l`cssC^4 z5n&q{^Vti6JuneR`yIaXfAn_3QxFBcAeK|TXBfHEb-r({w$zf_el(d{DgH~K4#%dn zYRo{sJKORf0nb@yrb+m9UhKqy{4rzd)JCM>d!?wyb2d~<&^WQGVVh5J?>(Fkg2t1c zZ#;AT8uD9FNkmy`OlYqlPtYFy@sA#cHtY63f?;D0x=RVC3?sG$uL;lnKnk4OnZ&|gu0hdYJMCoL0@Oe9XTB>oUyR=ttKhA%GN#PCh=+Z*CBRs@z5OIS`Ki)^27D30$05Hf-^B zroi1}zmc#fEsR#8t?#Z-rgP%_c4??#_6P86rMs4EqvjxPrK{F#pf^<$vCL2~!R*ur zP5gJfZ87FM*BT8CEa_b90=0IE%GH!Q zDvkY0|G_tqukzwOpCOElbMmd!o^tfjo8-(VA3foJZRJ{YR&I+BIDx%b?@yA*i?8Ua zSbqAm%6zVI=&hJRQ#5(66#Y;_QNfIV>09U>`i$D8K1Yt30>jP)$j4@!_i)r#@C{D% z>X%xFakHw;hZ-+)%L;Z7r3wLxatkd24ZG#6!bxMw22=+|EgJ!(st@e+|9k<@YZ3X} zE#;{<8%~QCCu+~M7t{r{EZ$_O|7plytz{Q3e@gf#N9-lRZo|!U^8p1meT?<&jO;Q^ zn(^l`r*LP)XvZk0FD#0TXOKYJGaKppaQ*dED+wI$1jg060i9STBvPlC2}1zOMC<4N zN)Vk3+>v6EcSDyzSy%eonc-$>5A_C)rDFQN-+v_8o+)`2gK^U=i@jMZMpPQAue+-p zapEz;kDhJ4SEF9*qX>x9{=g0=gAc{tdGdpsOju*8p1bI202U@QwBI$%+4p$%1Wd>o zF0GkI3G4+2VzMCTxt>um`t4^p`_vWC<%Ek0Dw7OOm#z{&`SI|d1Yk3tH5@hpO&HO=4 zZ^=Ju#WrROkWgSiWMnW9I;rs`v!3JULf}sz|ClAUVcBosr^b7fH01N@jkI}h?cMe? zzWhMv$;7`q7f)16url9M_$;NDlj%xt+xHxIeNr?!0<6-H*ECp9!kq0Jty)ruqQ*ze z?rTDnaDm_?q0vkSQc6Lzc!?UsjjwEf zHoF8+Vo+JcRrjbgC?<*~4s4SxO;ip6aCu>9TLX<60ZsOTBHU=CebG_gyK$LP0YhCe zl-IbC8IUWF((b!0G=T(U_kKHpT^H(@+hiXTR3|NMuGw1}Z_hnTmz)-;$+yndBe11W zR5q75DrB9=_om(l6?zIpF~61UxZ;Js#4NIoLyxC`wZ zTd!{Z!sK_#{p=w51);OZXPEjIN6A}Olt>gjx;Pn5n|_ex#5PcDQ}D z*6mU70sU_UG8~U{zv{)*A^GcW^DncgZ7^r&oz3r*D0rJGAin2fK;P*#+=SM9<5p-KDe!Sb~S1SE&%3WeFH=sJ68m@MxU$K9@ye6x z*AnM|P63Q?OsR8@USIiB*scq8z#Jg_K35)8T?CQjePf1GK5k1D0kNXtt zR(8}X=wjIsh zp@W;7`{FOs?%WWmzVFUbo3S207zxAY`CSD`C_e;-O314P{Iv+-Tj@)ELhkH(T5dy= z_$f}wS{Bslc)TmbtUl}1ANIPk%85itrQE2uovtMrjp5ds`P$Oy<2x?&n`ZQb+^<{e zZ8LlquKG3oJBMeL_J=-=VxJD=?k~3$={VBM6tl?yeJk;zB>(hXMI&O1%w;!y>e&tr; ziLP6*19Vwqwb3ofIOkMuSFO|(+~8juG10Jk9^1{V7WbT3G|fy|jW0SOm%~j`bS3^j z0y&MlW)*jt_qNCMF_o<&(VsF$qU$R?$7=&>=RWr#_1NYAjA--f6Gq zuHG)MZjFwc#wF7pkucsLB0fI8rMK}w-hQcG&KXYyYanN=7&7WCs+&ereUzxBBiC?! zbj_S00$wnk`k9=uS{ETTU~*nw9wR=X_CJE`@ACYLSP}0ScvNR8Eo%f$?8_p7n2UxS z%EIoCzjAp_JKjITH=W>yP@^nd8!8=GjJg9bw#*1BM?Ubl(`ZHTSEx9#?GrT<@#%6k+#_qncE{+Dy( z?v+W6tiJbwGUr34WB89P$?tx@-^qFKJEfaI3xAId|K(qUSgibOQygtg5y7#@S+kk} zz^%*|DWFe*hc_>AT7gnA1svqeY$Z?~c>J9>l+*0-))daTz6*= z>oYB<2(67^TZE^Ez)KKO5c^<&fyKo$IicRPA&|I+2%WGj_h-IPWbW`3Hf0Uv&0a0VT+-|1rt^Q=r23AZj9)OM46-b|XIl*ex zHAE#x3rYg@$xeY>r$$y3esXfHf@<98HA}^`AFgC{>hr1yr%?zc5u&5sPpO_oOU%P5 zQBXhe(n!@aJI=)At`%}-ko2A)71r0OAj(S)9795wso&zpppRzJetVZ-P29^4h`=&b;xW*e8^U75_IfW%H|83zc;k~-r-&^Y3hTdidA zN&ONuesmDJUL?ygQ@;KX9zH{_qrK4v6Ba#Le?0cY{FNolm7l`NaotUjpT{$B@jrrh z#^dYAo?33f3u| z|Mb+SE3IcWG@pO3CvhAb_4X~PH+N983FqM!5H#?x<9}H!&4tpG=6Xz_gQJpMK4M)b z_CD%Ll5ng59EyaS1S?09r+t<9GHf16Qva`rU-Jl!x1qd&Pu=+v+tP}KQX!tt(|95< zFCL?Bvt8v8ZlR??jN@{E_?PR_?4G{Nr?~n)f2_!?nT|-6HT=2xrlsmid@ZVDt6$#? z1RoP1c9mrAE}U$H+hTkjq7 z&+FOkBK}EzglU}ZrSQJn+#>wS$8&RK-qNfy|87TCAWR|XPXSoMX$*ycYxv0WWIdm7 z1uPOm8=rN|0+~_@;nh%8&p=_S@5upf6z7LHLb;i}GTPw>4qPs4^i{RJ;WJ)T`h1Z%2diVA!^uUa9<>DGT)Jd?iS3OuMf>LP7;NXE141T<~QQV#S$K2L&>@A zPP!q;HqZGIXfCfQaygd|9j+YIa8d{yd9iU|PTr=sN|w*i!C#!h0cp_7Nf`fFV_6-k zny7Wqq`x)Emf%z;{Y>(wfFku3<>{w?F`hoWj+K4psyXK!#Tc2f0TDwOJ%?qtZ^M~^ z3ah&er~c)nwb+0_*OgF5Xv5vQ`cCZ3;X4?c$vmh-JfWNO}QfZns*aUvH8)Ts5 zNnq4bh7oRc*itd$N|axb)8k;+IQ(zXato~;{^jGAq%%_>qurBEG%< zw5u(|69=_xg`F)k>kJJoh*y#VS5C{k_=DV3u)`H5JZIZVTd|VX;=-&Z~=Zh52z z>}-(`PtpEb(UaNM*R${B#q5Ruj`x(l{vFQJwRm0x__uN~x9BpH=o7EC&Q~sE|XB|4F ze&o`|WYZ7VCyUeEwUyWuR7-MP2YD*Jv0JjOnGthNp?;w?Vm)#L4_6%Auu4VC%k}!N z$lH$2wCjWIOo+3ZE%y*1&M?k8lKwifXS1Ao1QPcL@jM~dRX-}~J39p&3L3SIrrjda6Y!d!IKXK7qqQJt z^eg}!Q;T%-OCKhs$tw>zxg_l#EvwXl>OpqCVA3M13l2~x18Yy6D%oGxJ!X)WRHwY? z8FZPB`zYtN;;Yf^>1*Ay1a-}?%bx+r-sgK<`#9jRZfe1K`!-c$_xG%n(Fw$rV(BJR z`TbkD!h844ky?5^n`m@cj2-7`MTGwad=HtTyVXP1NyXr8Kl&(hfPqefr{JXlB{6}q zIxYlP51MkFGLf3+0rAy!2J#kR~!_zO@N~;UxW2{01xdP#yFDri)B@nJgj2r zJA_0P!`Y0}d0oD%rI4Ifhw8^9g6y4rtp-e%Dqk5$wDPH`$mKjPV#D8{7W;`;IX_MxF6Sd~HsnUv7i5 zMICof*Mcx!UdG6MH7BKa^ekxEHy$xlx+Liv8VSXa6r^$$iD|t5^bljH#V@U|82%pTv1#EVCniYqdqLGNVkE25xiq7#p+Y6T!srJpSkvm| zFWiqCxaEN}T$?#BO{gXh_ve12Tlf5L=0nud3dc*VA{9>YuOR=X_*)Z`OVJ%%!7G(w zJNlTIE707esJb&w*!_Es7MMhpVMs*Mo(0VH$1NM1N<+8Y&e}F4sj`0+Hy9BHh^|u2 zvEk`Zhb94Rr9n52)ti(VjB-M09Z1XUa(71E8^EK`^ZmNlvvnHE0$b6-3a@)>8_3ox|z$^?>>tWdM2 zj`k1dLsupf{r=3y)2*$_Jpbh1YWM5s5RnTr z;$Viu-5BD;xG_cNBL{t){Pa$JOqIl?N0`u1LLB>O5{(#aL14)1q*T7MT7IWv%hau_ zbWZ`6~n|!=Q7pkTULKpw| z;|J1(z{x~zu`cI-PuH`zoJ+BtrAop)m{l$|593#1AnNK;f~A+p)FL-jaVA@++`~{k z48|y3iFpn9yJlv$;GvQ5V*FC@VvT)(ER`$aYy{=E53zi4(F1? z*2OQef@F6wQ59zV!qmI>OMC~ix~!uHG=8(H3O#o@*hzasCGweu_Vu?MQqq?=qPpuz zQ#mR8wXSRJt3gtr?CrIbA7L zl(;^`k6G?QnyL3Xq};Yw$1r+A@U3_~g11PfPEOnbs3m(-a>{g~K6A9{3`(7xwA?eS zXee`IC@{sn>3!qvcQ1L?c#-Ww!SYJN)~=aEqw#bhF^`?ex5*Q&dvb-rbdad62Kk173DF-S2cx?1vdyr!Ih7JX$@YVVq} zVxK&|NEGikV65#8mR_>I+2t!v;gur>yJ30cwh(zzA(0B7+VSdhbR+J2@zAWa&NjB%hY^O*Lr@1jKz*Z;`|LLB#W2v_w^iBC@M<+3&0 z4ZwElj~YtD;!;uOA2OBm7%2%AGXEoRo}cqhLPI(;Cp?-hr^Ajvq7(b9OlQ#_(1{1?Eb0e4 z3>wEzRMEXqyKZLRnX(UhRq`o2&r0{={xao{2C4M2cklEm!g^Fm0Q?{4`Ei`CS>-&d z-JCnXWyH>0U0j%{aRqJXn6DPZ76Mo64)XpigU=8%e1~^MPO}Tfu44)ZUrpG8p?pCy z|Jb&K*rjru$72%XL+*nWT854aTo(j4l-YEmmO0x=zbm& z$9V+ybAaEZ@L`XlPz4BG#*n4mjtnBozv))lng1pu5e5hhNw>iO7K;9O(!KDc$s|4L z?Dc_~H-fnJamRR-hzE?_C~BVIyJF3Ktw%>r@f>nY)qdhvRCSA@)IN2Nr-TBv`A?so}A$A zhZ#2ErHn*acDH-r$7tCIQ*tUk!d*;4>NH|-^`_yfd?p0mXN>4K1Sl)Zz`Rbjb6fzzrWVg_JVH?e>_0g940dZe= z4fd~mgOJSnpQgp5JT%hE-D^W}@_XNvpmk!!dkX*lq8Enaxa8gh8(5EW)-j{ zso>S$vb$tPdeJ1($pY)suS~pTzMy=Gr9VP^UqEWKi;M(qc0a ze;Z||{%NjQ1R*u&H+p}K$Hr?jYqV0>D`OPrKkSDym_>`(XD?PU^D`?;wn09&Ef7hS zVclMM+253lb;PEnwUy<9!#QkyFDdI%lGi8#V?2gAvf{6grHb(v3sosZ_4VQ!%t7kr zZ>0-`YA3w<+-H;MAjW>gOD}C*12n8(QS?2C8*$^Q;LpEH=8yfe@&21W3WHE&Hq0$h z3Uz(#cN7p10C5ra$0QCrY+Fo^z1IrHq|y&Lm|9eyrBrV>r71rin~kVro2OYac{0*> z=Wh2P4#U_Ig+TU;5mOr8ujyL5QZBwuZPl0yrM)4pF45uv05}|=8p|f>->nC05|?Pq z!H(l|!Xskt*jLq@G_YRSBz%gANYP?y@KP*U9np`jPI%Jfh$}NBosU{>cF^o)r4J;! zeDCw;ph=qtWjdQO!ya}}l`kaWMrzVCv};sUpj^351VX=i7y`TUpf&~uXJ!Jsct_H0 zwT@WtyWNus>Qr4>A8pc(mR-GFU@q2#yM4okEqhU~a@2p5>bF!%@N1bX$T4`T1}Emm zRv3Q7@$hi&k2e2Hl8X-1AjW==Uz>)}4|tS}IA(de-J2VWBMpnx)LUC1o5L&WOjNIS z!a#tFZj>ZdM;Yn&<59=;xaLSMJXEuFdsjQ_|!nrXPwe)#P}fOAcwI0!!1gS5_BkZnJtFDoLd0$D4&R7ZwD2v~*1#SV zozIksf9G`98FUVuRhgofuW}|)1Ia$tP>O9m{XMsKK9U%~_8&nQHIadK%a$atFD5SQ zbuRa^`aM1J9uaty*=O?!vv3bKYeci)o1y=%Nr)l-cNB zG2%(>0?$b1~J%%TW z%yuCw8Ww3$faA>9F%zZ&FNW6_whiramV}Puz51S;)tYwq=s}NTC}{Nc+lKNDQ3*Qg z!OkCsOiu-qyMi9aD>pYhDZ#(v?bjgmSWEU50NnaGj3n+wYz-P}2Yjz8_YNuo{I5;@ z|6#S}olEwA7W|}?&tr@Jr(lyHG%@s9@FPO*Q6x2&ZB3xU^O=qnA=b&x$TVMDjUa4U zFuW!>nXI4Iy6vbzp&{o#f<*QX@&_Nkf0LP{7&fNx3f15zZ7v(B=QxwBVl1)yQX~Ew z`{ReTe$OcgekNuuF7qS7zOJJ!co6miX^9D!niHSXZ)w zOJWbBU9mV2%f8O$MMRK!MsWHk@ra|v0YbsGy=75sVn&NES$0u3O53%1IYqq&{yM*0 zU_-_PVv(9OvRNa^T|;6+I6YBZsF_}EZehcHme~IZU(A6v@YSZvqi=9YAj*#SfL(%O}OTLvuOt|n&%i~wGK44wZ}U(t(B?H2;JG2 z>Ui`bAC#oVQ!t}ASV#*W6BG|-)H_KU>7j_nan>tCLX*G6e3cFDG{vhenEUP^I#lM(>buGoc!SJ= z79>GTu!meZf;gXl0e&YOpLfFTkFW+&>LZ=3+UWZ3wg?%evG-V7-Y#~a-Z<96O}dM` zZICKts9;AywV+-L>kzB4(cawKpq{8BLyKwscodb=R?Y0$bKUvB z3Yj<~XYB+AfbQ*f7xt?$jFOxSKVhR{vum{~xA!jtF5syTD2(5Q%~pfKSmbaxlfQOr zP5rdNS8h#tc|L%=SbxnmVB3-^s~YD%T?mz$AyNHVB#Gr_w{4(SCujN&NC~aLI-_k zM6BSq@~efj-+t^ZKML^e8&MS?p3Fldzr_V z(dB?PDX9TE z_)L?>4Dy|XYjVapxk=T;*XQ3vWd>K$tunqIT0d#05}Evf$JNySJ!|l~OUSMmv5fac zAh&+>NhrAb;ar2|E4^_R`cy}QZ}5=aX0wKh)xw!XkI?NkWyoV`!$q=+74{y`&2|;- z#kDAEwOX~F{~#_HzgFIyp(5?OZD)uo?$H&STzmEjREwkCAeG&nP!y2LK{NbGmIR%N z$~4__Hbch5&}AJ7ZsyTiw6udzDCNDBzQo>yu(17@<=VK6*z$6;Kk!nzHMmv#D<9+~ zBw+kgF@Rr?UkWI|O1(!ZI2wa)l%CCrvUs2jpL?5Kpk!oxK1QEPlH{+;mtS+H&orp0 zxKFP&&yZ{HDe|dGs<0y0%#up-5tGH|AE=y9D{h%HLsoxJyI1T@@h(-a@Rg05$F<6J z2c-L?L;2O1YfJ+ncSHH=Tp2aetCdvDm%Y&=?T~#1=imX;P<0V9{x`@W?>6o`#p1j4 z5PR);-wX(rCYO(!o7BSo!Pi@mV;!wHt=61>)C#B2&1iI0Y}vBl38wBvmsjphZkI7D5RF*C+S7bi(D~-EN51kURd~RNX!X!|CMUcP zZ@bh)<3rLecRfaJ{`5yLg$PR0j9gwc4>2corwGp060|6vl&5-^ zZvXmmo>JX&N~7Pd6>99`8MQrbDntbuaEl8z!wjJWYmZ90i$RD)@Z!-*$Izs+PK_U#{oI z1H))^E+vk$!>O!(pBESGGMMF*vwHxOoG-X$U`IYBPd+n?VjMW81Z6mJJ$@D}INZj! zpFV>scB^tYSWv~;%+5AdZ=zPPe!B5CG%|tz5tP3({g1$DvQZGuJfOlMjre^n%IrvA z?w-eoq3WntIQ0eh$lxsJvsBjBh1!HVU)u|CvEK-O2{0d7AL2>Og>9Qxo6EP1(LgJv zNWS?8<#KEB6k2__G6BF__cfk!?ah#mu~=Dsh7V}_540cD_KkOd(tnW^TmLNd*c{_O zihcRlYpwowf@htjR?Q*rd_eM4X#bYJ2ii8CIG!Td?_PD+#a1jl_=P)Fl$%+uk8o5? zW5*Y_rKz!HIdo!A0K7lcSC%p}eewtusG*wAX!yF`GZJReKGulXS{8{@f3R)}75$;# zCd*zmChIU-%Ay;!Q{ueot5)CLZfU?SVj-LY0LOnBzm5UgyHIQymm%?Y3087-i8BYO z7v;V#Rt%1Sxr#eZkSBDCLq^M$t57-!&pc#9E*k<_=@*uon*~v2fj_a0ZF}b6N1F;6ba*WC6J;p!5xV*ife^^82e(QSi^d zfA8)A>~b{HmH;%jTsp4LuG-QnHD_Lq)xDkOUx$)If{K8k^dev&H0gw@^n@OobdX*G z5}F{rN$&ya0tvkaLT`ff-U+=*SE*9{CwtG{2Qvq=)?Ra#ljP`2^1jb=-`Dl=)9}E* zpP0>gQqxf0>)N>_1|MC7v-kPk;rzYW&^4WA-S}yn-ImIv&K8g@#%>z)u%qQZgSU{p zBH17KVVG)cHlIl3TS{gKB(~5m=TMY%)CDawo5f@BXDAt(6Z8)_njHJNGSOgSGpL~8 z!K2=H9M6L?^8qt1*>q^4J1i4BnN^TmT4}TJh@lTJwR;swxWIN<$wWfz1 z1G%B34BgGX!4q>j@i|OLW;I8u`Z;7W8xr+c2EZkWqd;+Udc>LAa8AY+Lm(l(Pcoy> zQ1mZlk=luH8-BssTE<5uF*`NqnoV)Nvu=#evY#3n&Knk0IdRE`sYLM30)B$nzR6Xs zpGyiq2)@Mn>|sUY-pj|hvlxw8k4RdbW{$TG7{6=mvc^*4X)Fi}iOE-*31Z{mSO^zi28*qI$lL*Z`P*RjlBVuSz70823Et|$M>!neq=5#UV zd{}Dbzhj~#M{!zl>6s%E{S<5KJ@or)3%$;tpis6?`c`*TOJVN<==z`)4C@Jya&-xg z=YvoeDUIoIUezxy;U8=?P!$o^-O2*EQPAtif%Sd9gjAjnN+i!M)-K`^y9`< z5UwWCl5%h%3EhVkPZd&j{L89zjPp=~{*y1sdX0h_>o>ZdlN{ESb$}lE@2P~8n44IS ziYDQzI9?CybF0U#QjJ-11U&p18vL{*Orh195SyDa@+HwC)D};1wYGsR>sM`Kf^5Nu zDg;&7zJ-00k0(>+E~6;vJ*Ru+QjynDaj%SlUmVkLHcWhuBgUx9fq{zwkp`MATudW5 z1@89mQLJRvGy8=BlZ3}RCeRlP`c!SnN^5Jru}y1(4qmJr{nj#0fs!l_Ahfhn?J8Bv zn$d-{$7!Vx*@9t2gmEE=xoZAey+Ym(vo9Y@g_Q~KzQX$k1|MEZ2O#3r+>-aE1RX97 zaaptG(#L5Lb60Mxicbp*Zi9&b&Xq=;#HnP!_C`K-+}ofXOH^j!25dMKQ7!ZO5Hu+A za=g>OOt5rFR?ZT9A0M&#o3t{M?Mv(cdPw(TTUC3a{qV&fpvK-~i z_;{Mb&d5wlx%J*Tw@!=N&l^H>-BewulvJyp#CtL@;4d}q>!u>3z(V|`O>u6mZ^NC9 zceFPJX`F}|BIyZ_6Eyx|R4l=`xH(2a5Nt9C@t=Lks67-Vty$@uY{cbdQt<0YC6_=U z|M8uLH|@UeNA)G%Vdb~>^c;nCh)Y?rpLh)19&hiY^d@h{ zm!QOtri{vFAK=VITIA@&4z<>Kytw}DK#B9(!9nNUDQYh|T>_#76ZIiBau(2|%Z^ROVXlLTNF4eW|S>WKYuu<^rV#_-IZ5E&y z*W%Asz^7_|_#a--Q%1pFe|PNzdx)dLm$_G5kbW6~pIzczXK}ap+#{zybCdu|>~q*< zzqhlZrrge6ho>cALaupZB@%5(5Bg-yLo{-=QGYDCT9Lh_VQKx`PJjCXbKbtb zjAz6C8WG%Nk2eV7)PF;LeDRIjTs+vW22P@xi26rPeD)3WA6|6l^F>(sjqvUCBF8d& zeQ2)QZ-m|q`z%rsRTvk*-L!AtEbtGnrlIuIJTX1jlXQU}v_sr~!3Q*aAc6MYv~sy@DfvEmK>ElAJEewu zaH1&F^>P1J_uNsRAtQt3=WC}KgaD;vP~(4iYNe(cSlPheQ|%=tdUbKF9uWyszt=7Z zUSO0GF(uSgf+48Hhh8-2ztvK-6WA3#EEU1xWV_y%#h16Q9+c~45SFIB$ZpwSR9e`f z9osFEK8!Y#?-0-*O_PP;&huBC(+#||g-fR8>aPfJ0bNL1;n>y|I}vBH3S(_<|6E(_ zX=?GMx3V>*s>%U~P699faO{&ad%U;)TY^;UU!U>Y-RbBM)sg=6GH3ki`#!bRl$)Ha z^M?9bDQm=6wbND!Lsc7`<@VL=H^Tiio)<-C1&*RcZORQsui6kLpxa*Ywo@cLL3GF1 z!tc@f|=t1l`*m zsGL$NoMnEN{`v6~jr`GF4;Lx#r_h|YPs#~qTpLZx%Vc!TZC#(6(#BEzxu|GLr1~J& zG~W1z^f|{WJVIACT;^Vs8DS^;>dhhADy|NB-q>@|2sS!CP4X7xpP(4$;5L&Rq%R~q zZoo=jT(S-48gLh)-m$qj1hBj>-Umm$iOz}rHer>;NkWTjAWL4}{x);vEUp_#O&&<1 zap5S3s(9_v3F?p(-%+uWj_C^2i2o(P*ohYHd-w_?Q?*etY!~bUn$7vI+74@fmBRX| z5YBTiM<}cP*qIAjW_B`rnK<{uprRd#7=eN&Cad1)!&AOJIeM-kbi|mRP#C9^?ks!Fg`J$q&qSRk)`x3(9SUOoK+C!d9 z96=d=nyj*)H*tU1AA+;_0(00t{`r1QzT0E{TJ2-~&v%C6MnMKYWiV~5r-~S?nfg)s zVHIcZ^n9e(_2lq`iA5=Y&AYSRKP8^$YsZJiJ=CZ{hSS{9|M0#K-!gCHQ}607^^>s{ zOErNBz8(21-_B!*v{inGpI}M1=6`f#Y+Ph|Pylva4j3wXod`qRn`N?~I7t6sDo(o? zeVp0hg-Jb|&LV-%XlQo=!3!VSnw?Kk4L(j9&)rk#B;&#FwA|9E-e^@kLAp+#_8)@z z%lLMCUpp_EcF*RYyHqrr%IK>fs5iSkXNX&cMhHzic1<--1sTw zyPjMbf*#?P`$hlZtvb@D8l0M^M5C}x;+mqiO$|jevkeR-X}cryOm6uIegeFd|L}gm zChp6NpTpS7AJ->UVbaMjDzbiLmDeC1?u|^Ob}W)oP98i@YQQ5n0vh|(8#a2y2PeQW zhoFXHlU8tspfwfA_hl{_em;X5Jgb^Rj7xm{h*!dvMu%^RzyDQU%?q*8xJMFt30DfT-4}tH5Zd*+#XnCYNywf z04wo3cdhWdIp28cV)=jyLR4s~HE)%!fdkpqQkubSFwh&Ppg)TjiEDPoHD; zAJRdV-|Z29O_b%|FKb$xOhV4hn=1eIM5=b>FoI0`Nv{8SqZlA_?j9z!mK_`<) z3z>O`i^bcaZgNGW9R6uQ=hN!Hw?G)OqnR)_Qp|&dlc!&;ugcHg&eOhqJ~20|bZN** zocOuW?Jl>%{zGyv3wU)8&eF^!ywk{p_wZ>U@c^2rQI zj8R0DFcac2bWi!ixr-&%7nS}AH*cw>I9(n!wm&W8ugR46<}AGQ#1^Ftj_I^Iv9(0Q zA+6hFvp+w;V^Peeg%b$j48mqsul?b^KdTH!6;D%Bnr`F&AsT;~59TSJPE@KOJE_wd z+_;$EKtVw)o=ZjDbzdf@`TniY%O@;asqBaC+nv|X467|!X^zMljIMXa@)A$PHC&9^ zZ4DVRH2d-Ny!;bWCdD$Z1OLCl9jUjYL^|!9&>LxijY7j>y<>`hXDxzfaS5N&w@f zhi(mQQI_#5J}*~2g2*UmB2n89zJx9 ztlQ~MbzFquWX6&SDCdKb(mWWRaN~ zK)>t1OpC3qvsuKP!}LgnapQF5dU@rb5$E-m!l2wx>)>D9388(*UQWZwMUIkTMBS67>30~8NzNAq8QaWKrUsszGtCA@Gsh(jX1q`5tVO;)c8|{rEj@cBF`ndj zL?u~Vq>Pe}34Fg7Hnqg1?1l@_Rg?9TdiH)&Z-dH_Yidb)$f7KTQ?&SUsuViGCz6)| zNgWP{VXuGo(8)BmE-P^%?fKU@_is_AJcpzmN67|fdM)KbM_`D+jQM=4= z!#xA%Si#qybt!JGV7KdJCY`F*@wl^>eO|? zvvR_uSjNl4^NZUJE)Fu>r3R7F?%>tD@~ZzNaYmsR?8XlmGGTvub8+J>5=N=kmQ`@5 zWNJ8*EuPz*wx9VUyrGoD{X}etOtS;LCS5AtWG%;^s%}~);vCAoO%NlHdA|nIhjcB8 zEG5w0_fe+pVHw2e%tq;?HzAom^ONflrpw_e^GrRrqwYJ`>{ppR(OAHy80``|YOY;~ zY{|us?K@nDH zkp{r_Q}4gjvk?OBsU<@$$;!HS%qO={ zkk9q_(^a_3E=!`9WXgQCuXr~}Vm2}$_fGiZp{~=guDW~~+bgVuLV&^h?G;WC9stBO zhJSJJ403%}1=JAOJGX)vi*}@3Np8%g=PvJVw!0@zu#{PcyaW8344!r!D?1(BPcBHR z;fL4%CObdTfhjjEZ56XV>V{Gh*)O4j^kWcX^`gLr*nl-Un+vi-^v?JaL_6-d<<^Yh&He;UT`n20 ze?I|m_-xbh81`n_C-^k=fqwmVu1@F#Zdx=wD#JcSq#k&wTx(`w&!#fkJoa`cAZ9fZn-j^D7g-mxi>| zDq`Z?TfF|)sAWmLe#*=XT8Se6Z>?}2_9j$Q1<}*sezkLHVCCz|BtAZ=j56m%!P8Py zmQC|Q?2Fi9bMaHL3FcwI{zaAj?2NJE85dZCx!Hd^^hYY8OEKvSMDX- z9%3oON6*Z#|KasHDO}j3Kt%1%zmUB;&}}J#ZhsC06WMcdYky}0T!@$fje!NIy3y${ za+h?U2Gy{K6poR>uO%m!yHkm|cJ#MXnrUUStX`q7KCDhMQyDLUmSP+9=SljH?H@HL zn+@#8k~LMCG(qz?3mFC%1LD-J`JW0`KkYe7&IQq1h!O{?pIw$ZcwY&5E&=a~j}?{U z0I3nPJ4zCvGyf2obCar-g))3vM`wDcrGyP@oV5Rd$YjSDITyZRu5_iByp$$Re5t49 z(j@;dZ;;R1zh-!Il*vzGVNbZg+&~(LhV;Exr3kyRItA8T=&60qCUv&Y7ZW{$^|1Em z|L9rESN3Qfw{19o;$RR8zH{x|qJ0%u)~8X9pV(Wv_2t}Vo_4M_odTrUI*G5~+moqc zMeOxjDo>> zJgrH$2=C7F!8;vC9SQ@tggKz8#$R;h>9J|Lzx{__BQUod;+cHaaZUh%q^{}zI<-|`-_Fk;NW;$1$sXo znF*J`b+WlC?ABy|abw3O`#0J}u55`i_~c!z03$z&YBzF&O%oQ|ezr&(bNAYtotq3C zKymA)bx*ddv=9}o{#p=VUkAhfA0B&0>~8|k-mG_yU()?zw_~j5s2LqyX&nN)+nBz& zJo-C!^}Wa$KFC~c{}rrw6vy{xbm;6gzaUasr(BiWaJd+edP_Ik6S5uI>S4ah!~3tx z)}3P6rfUN-g?T3EA1E=X-mJ}Q-?z`J^(&*Jz@3HbJ*SSHb)wfAwO`UM9rw##tnj8+ zThn1HZ$@c2@g*EW&ys!0*z7Ic?DXXQ480T9XK+wQ;7J!8>l}Gj)o@0sJ@$ZlG{I`m zsX!1mnPLP~^ICyNq;e2pknnBBe;2&*Ql;SwA7hh>bV?Exmgm|p z)dbP{FNUC@dD=!b(VEo#W{m>HaXQMcIAsv->Ar{ z+xOb?!Tvyp5s8K+Wph$wCtOrN6GH$}qNgM+qud(Y)i2U`-BI4!Itbs!vA`tf7ge}T!pGz*P zq6?z1sVxqYm|(R6kCzMlEaD-^BV=wwbM}^4k@MzcyomuLK0aE*El6zCLrzJZDbt}( zdqCf9U*BbbZ(Y@kuxQPhJ(VHeGAYkQk3knfne*}wdy)K*&UcWrJFb-1PFY|!SQR?g zFv|U*Rm`JS$RiYF(O{wpoPfeX1~Ybq{fE2oiOGkI)XRbUj1m_qf~YgA znazewKNz*1$H;a>CaE&t1MLYi#0c^}-M-y%R$>F@e|2K&lQxZL3QJCX=Dze>hqfGy zW-z6RF!krcJNx7y{(bMMhlH);NGp2!;RjQt2Xb$4=6J_$;4GcYuvps46eMk*WZ;Nf zcg91noM)j?5LKyakW?2-R#Xq?R?;x7%yQ4(cg<+#`YG>+-PX_y#Nhmvbb2)9?d@6i z4ls!PpocXJL291-VyTN+sIIYM%-D;=G7<-A4eyd2qgT-^4aK-7&}*-86a5(bP}ySP z*2P90Bc6#lI{4-dTmB#!VFQA5>uXL;Qg$YCx0_FM@>7*YJZ_2e2bxrnk$5pvW~{~h zXW5vP2q@FkwxxZ~5$huyE2V>9X_+>Z!nFTjcetC@Zb;#p1_QB*VG^q_1!?1(C&f-%GP7 zFZUl_IM0L*#WzrV?Q?lQ|*NF zD!aJB*x#4(yc|xPyb0V6G<~0^(hHogDcvi;ma|NOqJB%ehY++&EMn^JViR7ZF2iL{ z9{Y>9hS|3)fm$W2LE~JO!IL^vt<(7$CB}#sxsz)7gUb+rkjI55+AXChQY+eQrwU|C ztj3yFQ0j??yAcFJiq)f+ zcoy6yZKt}5&5>DMzqSj}E$(}vPd!1fAB{73!u9Ml#3ygKt+yy_)x21gAu+)m%SovZ zggV=OsFe+?J!P49_BuE1$2)tVArPWGSFhEy2wV|7)1kV9*n6nh zTqp4+F+G&8W#Bq_@#b5Cd``l$-9+DsqmDQwDnD@L82pEk( z_{R6N+r1ntQP1HxJ(XIPQHl#GrOn_sUb;86u)c9Mr@ygo)u6A#cZFxcf*f4*PSWN9l4NZ%gLL zt6FZ|$iOk4;xXW85QVq~OJSui$LE^aktplN-bD#3lcA)_E9laZ46FJh@TXso!)(}} z*jf0k+>jorgBcH0d4!$B#F?w@{_I}HBvUSF<9is5-z#h3ox#?ub|mi)x%ymW_4Pld z#Jz^!@0uRe`h9(jrZ-TC_>NCPPspr&RdkvciGlo9AQV*Lg*fVyBwNxjE4$9uD6Xmwrog*YDU!yeQ<6L-*y* zWJ!P?-K9K=d1$B;?R`@608X;MoPeQIH$(+yod$&5Nu5Y)IQrARSh1*UbqZy~HBU}Y zuf9n2vs|O0-r_gDp5Ke=z26lxQo8W%sp>b?=NHqt7-eV~k#=#gdox{lr5sHnZ$(ad z(Kdz@Pq^@TIG;Vs*IyWuIcNUPw8c;U`eVO}eB;uZD%9oyhAZ1f=G#B3(+a`u4SJm6 zi*xtk6}EJvx0!HRzxeeN-szT(wQtoRpXVC!fSeWbT~|0j{)wtzWUxhYkf3HeXvo)w zAsb`+w1Fo2W+7HJ2=HSZ2PoMCP9e%!2SsdJm4850t*@4^-~Q4pp2|1D?D3`xPV`o5 z33qajbKrL;1mZS@C{GpMGM=h3mmS7_o0g_C`L+QPCOLtefBo0`G3K_87_>B_t0{9j z?bOS4WK(i(tJl3_i=J6ux^fBp!F!&;1yLyKfh^gDV4S3a_^(Os>6bsont%#4(GK-u z36B{+CZ%AUIDD0GHt8S9Z)bTNmO?CKUY zHDr<)F|fl{B7?yu3}j0#a{Z~VVy8E8pt)>(ep>w!pWwuE)c5OY#Uz?4+f*e&d?;ff zG_$VGV_K>dA(QPox}d9b1Y*~->>88OeI6XE&8@JK9_5G?(ii|5Dh@XGQEKX+Ed4fY zh5mc&P#|+lP~c7AUq;K3HQbHE2nU&BZN=y`%>Khe=0}$+MxR-v+3 zwgsQlZnF0P^&nz7PN4DyBDjVy{>%U2;Qs%a5t{p76h1s+Lfvng!fIp6+MT|CrNGBb zVhDPrg_(DP_2sUxk;T6IF3CWYKN;-1(7=f~Lp(b#iAe$Cn>$AhrBjj~Q|V4j$hxYV zx({dq$?3(V#S$VDQB9axKwoS_GRI@6?QU~9GwI!}13E))S)G?F>GAPoVr(C(@-MD9 z%IV!1LcV+e>ZVT1Wr~j0nTu3nF-AqA#vVS z?({aoI_M64Ud(=Lr+x4CWr9RCiiLsTKqyqdH_7_TD~^{hl^(3J5&LnW=8U@Ip<-jA zG?kU8g4|1Ow`VWpjJf~dbFgI232R3VGwe$(cN+EfTfX%EhGc!rds-4-*ltF)sg^b( zBm^cx5FnU>j_)r@%CJOUG~Vey9vJ{^tQ-@gemu} z_k;v%(uYObv6uBj0ArW*>=Mp4`bzuPso*jYo+0W`1 zOv0d(EG%v^5Lc+Uug>ecsW^D$wNRG)6IzVqInA%KvC43i7LzrN@2B3|cI#o8+<~?7$Qo({Qg>lpEH@Uhbi4iARydI-ohCy*Hgh&9W6sEB z;5cNG^)}^6$v9ld#zDNFvy0w}bot_+Nz+=t*x+7UI(tc+LzdA|<9h?{Sols|zjK=p zs3!ZyU&wgOFD3e@!b)RsjXFtE^MvE$FO96Y7C-%+x4?S_4EQ<-);#uP7qB3m|d`GO!I6%v}i-$jrC)2X!j^_e2h*as&P3dQ6> zjr#iXRtS(xkb&b=A#tM(XYImu+HeUJOG;!9se!mR5ff8?c$VHeW9O2r_kcW#$V@@l zTVKNZ7Ds!TOA1wWwec}mY)vr=kT4tyq7TarnmM`TS%!VYY59b{9ml=rpJG2GsqOjQ zYi#pvs-^PL5NDQd-8LZnX`+){?OcDFvE z7DWc>Z~5(HfuLZnxm*a=2d#zVWhYnqL9wuHP&hVQm>W~H<`EWrNu5$OxHr_@G1mCQ zR|wAF$bEHU1c`*492z#2qnGm(y5~zgZWr}kN3G_9$o1ebwh^|HKS4v6MQ=d`|HH$rOag*MXWhG*!l!}z@%=E*fIdH z=m6x+dBG`5Pv1aJ@t2m6^`5F)n2%-QkWMU@@+4cQwy{*L5jvZF*Z`Yh-;`!9w>cDF zLB&H=N*D;75`-$igleu{`pwX-MO1d>_{1;4TFf5#_tH|P;C$lC7FO(xHwFor6k*3~ z4P?-$>E%}wzWTeUwDc9z;C<*jpQ{7B)*&U*h6`fX(%&W^4i5goHfW)Ld+$ACkMRTN z>ED&6E=k5uBYZ+u4fja;)#JU_m@v`(T*t5Ok|(P_W%PY!tIcTYYG`+F7fg)U>Q|O! z)n)@qT0BYiugk1=Yh8dV1MUp(R922YvKi7@2%k5oj+0sVvEhI#n&$7&>fWCgsMcOv zrgPYDW^ucVppK!|p!F~Y_r#A6z5ZGM^E{I1D`jxpJ{mfCFiY{ZR%<5ta9{a1RaI`! zjm~3O`*V)M@kjL)-1o<7lC0XfH19v*hp~Ged7qbE3x3oWK)rV1ikOO^cYzzFZ4J7c~rTLvVR``N; z@OOcoa9W%)taD(dvH#WBr~0074T*#4G0L~nUpi*jq#P;g-Ah3dHglPn_my5th{g5W zXAlc6=YE(mm+|_ucTLB4Wyz`AGum7nb!Mh|K<5+z1>7X0RBx6J5^LI?!YJYt_vwN9 zta`r-w*^(DU;AxOx2wVaVmxgIc_~Yi_Y9+-$Zpi6^<~pBu*y=xc~AgZ+u9z z6(^MUT4^P(aP6Uy;^n7TEZFMg*PR@j=U2Z=9%4V@J&TCVwvlT0J)S0D5=#*Q9Zt$f zrEYH9iQoD(A3hcC4SuJ;SF0gE@bTaEJ83FngAgHN7=1j#&aL+^QKCJ;ti6I%lqxFhu$=xtj012#H2ezD zOCO)_#*zdf3cP7Xbw0xim=#p^yI6SPv?ejE$NJmEaZ<qvSc)CIYV?7}V}pyQEJTs|NHMOB!!h z=4CGS$NpY(akuSh{1IvLsc9`e!+}=P?)Sdg=h2~khGzh7FwKr*R{XcLo?pH4kK7+| zi~Bt{lCQw&WAH?2jRTN*_!cZFi)MYeHvoti;afNOahiwrgVnwY;Fy# z^BMk$5vSIa-hhVPQe>f%(o|ewhYa!Yv(E343Conr_5(ia!P%dJxC{;NmH)$od2HPm zo5?OZKdgT9skkgR4#i)hDk|m!Xq(uD%)mhc6X%k<^AmbiH~ij{0FB^AL4?dy+F=t* zsd8y4`{uJK3Q)T-mk^mI%b&z>YYx2mXGx17AtNt`v^Lo^Xeyb;0%JfyQ`4_8T2pLd z{nw{Gnc+>km_j_JvcsCH3P1g^ND(DI;g>L|ks+<;yLWFd*lr2VD(ImaV_wthfZD-g7QqVM=A- z1o+?${yp*jd&QySI&pL7zs{EB0O?J8Rdue~u-tM0{fEYo`f0HQtd2nKL@64;>+rNU zdH#(Sy*t6qU1KSD5OBp7hx`xkq0+=~MNld~8AWXT7fHR@8|H;^Gg{jft|BR_D_8@G zkwG4L&e=7EQN0?b@TpBhl~O?@9k;nqDPeBtYXnUDF^tiHUVT~qW6$&Na`Yq|4hN48 zr>ix8gZ2xX8fP1gU2^Ih9b*T5<o^8NMQ=S%dChJ67`mTj?IC!lkfCBm34KWVa{2SUlg-baXtSYC+Q2lmAKdDt z#Sdtr-)k8F?-a5VOyXxFa7`csJ(YRp=(O#lo|R)Rc}D{lO;)a-j8A=;M7<@$T7^Dd z<+iXoDMxIM`OaG=tuGD%K3cJ@}(KNFi4I9C2kh{|I{aBnya07$!`eVzBu{V*s=+lda&RS|IO2&D;sKFE=J!**QPobXkp$SA-lrV%yM%S4nJE8U19)rvU zo~nlzbH<6xhYE&LLLU+VuQwvDxk zxCg8bAJM$$ST!MJp;Wqs|L*J{a|-W0O@)?=w!g*}W#_y)7U*9lqBR#Fp~v4h1+&NI zSr;r6F&WzgHmf+t{Uw#Dcc_0C)Y4_5OufNOQB}yO2%}Zf^hdbak2qxAa44v^nCQx2 z^`Qr2du7|98k6>&YBxV)b@!dF4GdxSgWGPVUdM<3Hfw!8rD@mg6hPOx7NCjLA#aJl ziIlkoeyG3U2P}r-iKns?J-PPPGyek-pj-la@Wig`muW;g+1gH)+F~o~D4xDUO5_?) z3_W7GrR#HpCOe}MY!-J?2UZV;E0148ER~y-Rm(q$KC=H-{+MR%gRjS8b6Zox7T>6w zh&m-1E0A|OD9sj8Wjtf{yxFv=gxC_)1bHj_y`^P6XJB9qR9jSMPRGxWHLx}hTijW} zx9Io|b5MxFMJ9f5QX=y1p5fwo<54z_Dr1ye_C5Rk{P1bXwAHQ4K3%H4z6T`Y3+H?8 z_l|;`eT`@dqD zdrx}YzVjvTq-H@|YP6X4=ilX|&PtDu71`0|bCIbe9TYo#PWmZWg^_Qtfg$`}!nSI$ z2&HweQ9a=sfc@YyO+%+kWFq2j37Kxvg)c5mT*)T(`RS|CLD42}!nEU!f#YvP)aBep zwe$X+ka?Jw{(kzR(EA_t2LyckObV%Z1qt{Q(^2d`D%zw3A0?S`%CmTkbz}N;kFy?Y z4ouE-^KRYAOH7KJjlyKQH=}A!Os=HcP&3W} z#~Ha~4@s>c7b6hAx%t}*>l4&%<%Yqs*M1z^|7)I`f80~z!0m5k`<7(Es?ogk-f6lg zA&he;3-=3c%%6NzN0&jST5BT=|6-&KNm=^9?V~87Rse%Nj}X7F$h2vo_Dx#??-iLD z>2=_P#!bWFvP>^0iwD_=OGGXXF5ppIa1+&7s?tXMwXaqqnpKKUG@M29FtqC9P1i^| zH_ca1ce`O1?oEpskZwe>JK}+|SzoQ0FvlX_>7a*GyTgy+pUrI<^HI@R?6K~g7XCpC z24+$MePyo&Q&O;=A6kc9Rv%Cn98ixuj|C9Sp|kZeU+-bsh7j;fv*d~v-{48M3B4_C zBhKUY^tmY4C1baRDH&4>i_~mtQb;klK(8_@-N5giL+kjHN?(^1ha^}I2{Np*jSxZ5 z3;^kSFaN!n&tax?VoULrV6s0!I@rgR?eYSCJYwI*^QNBrSHx}e{koCQ=jy_a{v<(=kRO$(rl-K|Gd^h;4{QHh8eONvV;XTlV zQUNaXVgUWih1Dgz$tRdMcH=EYGY(5Uqsop&e=;o&TdE$xamsHgL5q+^BAJZiyT4V= zbtt7tv*BN&Yi!-nS9Q3Dw8F<SYVb0= zYTC=%Xl*2U^ha0K(PBM}Qt;8(KSa#npmu=p(a_qtC$2!!Q1sQAPo#1ldKYxyqq|8d z7b3I-nD!6X7u2$@$5x6@=NIqycREzA$3!QmeJh;@CFVwHku1j-HwLyl#e?^d>2+yM zUy4kp-!&(06sZ5x!XK2%Yn6+lWnu0-6WRNaoK1(O+AHqfHhx?I$wkRhu1OV zWBjh2A7{XHGkWrpO~BFZXO9hE{)C3Hv@i1aUD+D&E~&iULnG)aEc}N$FXgn~2jPBG zt=O~poaFE)?p#2cKB1f&ud1ePsIlZm64*J$jeC9kOInkGWVTaVmJ7Z=&lhOXWNw!g zyWKbX%W>br?_>j?EE?Qv!d<5(Oyd7$*Q?lD`FAcYzIqke zjrzqK!c)O-2L}3gCldTND;dhTrm*(gn>nwTJzC35q8`8hGj&aB^l)&z=D1yFJB4cu zD%w}GmD6|9^Oz~LQAu>JQ1NZ*7H~&5`w2jNPukz>M*l3!4NO1GwpkFLdIgwxe&y4{ z_4jkoyZeTERe7J4rzrLZdL3{w|8hS_VPHxjl~G)$b!g<;bED6i`&or)yN~AyDMvi4 z1~9vXyH&(rFUO>NO-I>{3@Mc#ntR#|>#VUa|Ds$DkdOYUt$i=BZ)Ux{!)=$vHKb`1 z<8JtM>iVs7Xi6|f^Dj5nv9wYZK{5qR{!UA9_2m*+I?aZxIYOccV)Gun&<;QwVHWRn&?h2SNa*b)iXlzz{n6^z328A z_Q-9l+p8`G`+ccW(0IFt;%6IIg}Mj{eY4iqo**WQLeAu^AI@Px8Ud{Vo^3kLiXfpr z)Kujn|2*eOallmMG*XO}kxF){xM&Fq$&DPyv;`h}rjRa2{t14|PWep`#fZza@zuw- zPfgjpzcO$PI0&(OMQ7@%@QZ|D0k9;C@~Gs^Ihn#18E#s4p5V`zb0%PqsaYiI-K~>` z8;f-eo2St{v2NVa)4P2qK3cV`Ql-X)I7NpCW1JnRp_ni&tokJ>&Lc@STf^O|J9E6xoh(0>*DW))Z2dih?GK z%GAg1L^vuzqX!)_Pj?EKqiC_N5~+g3iGg3|OPPVslcPb|g34%`5Mv@$+J~*y5Z+lt zd?;-h<$IAf@>qhOz%>@@aSqWA6px_kKRi}v}t z<{5m*JZQ}R=407zmUmF*i8SZT+3;^DoO&iUFh$CEGK zBV|m(k*?7CXh2rra7MU}!({($7t@!yl1z=^ON$>O^%&9mM4gFCk%A?*g2fLE!ETmN zqZ1<-7@9>)OFKwQ?Wp%ngO?6?>~C}1n>qbTFCSf;Tp#bE@N`_1%-idhuH^F;Lj=~8nn1yeVZXhhb6)&1^o7mqQ)Zv`|ya?UHPPb z#FzEm&!*C`FM#d!nXk7NRSU67_?X(vvYLG1A|)m!J^-HNi5F>?*^KaN-MvoUd|+bU zG-}DoCBgqvr56+EhK+HX$o1shHjoP`<6J`&c;se!B*EhNT^B{Q_;SRI6j{pSwd1jbg4OsC*wNF(e=U`E3 z)=vo%<8al>&tdQ%5zKGN*d)1t8n*jao@HOrZ#A-<$KQHaD%9fmrJ$N1pjMWi5@m=6s6Gu==*5 zdD?`o#b6d>fZkfTiKwO6<(oH!vS%Zx{Pffsa@k*Fv%LJ4&&ghkh|ZRoeAu9+K#B|@ zQ1ygJA0@IS|HJg>O%lSn8CesVe6yA3vj-l-)q^JA2qSChX-_T(nN1^UZqBL0iaEi+ zNskn@FD7{*OMf4R8CX$qvNp_gxIl9dBPs_fV+(yw?XRc2EEW$E8V}W+yt3b z)Pb96&=Q_L&;+@8PdUrYA;I$>UQBMIk$Jsb2HY~a$a=`VXT)PWl_HV4Q4anVZ~*$* zw1hrcjnydF$o@hf;2*+{kbkG;B~(soE1tHEg!O@VicKMr z@t)*lS&Dvh^ZCqACMnK~LS+RcWlf(;&jA!18fIU~(D4o$#%M+e9q5Qe9B)^0i`j86 zGcePHC{T*GXmKxAptw^Uf)gMVFGYj9LtETkiWdnMq(y>5vEc3m ziiF@&C=TVDoSA3NGv{W`b1rh1eYKOl|L?oj`mKa^7X9x6Rn1DTPY~7z<@PlYzSa_2 z_1IHw3@jJe(U~dddHj0D$rEwH=ElJK+}8H1EhLQv{pcxM>)d43#;Y7WYUBT z)N#G&T%1I@g_DexZ>$^5*A-r9sv39!#XMloL5sZY2z*#7PI?(1tPNJzX?PE5h775X zrnEMY>oGUX)xJd$Fd*lBSv}GZoxn(aQ!Z*@JLlY8)T}$=P!)5UI%cn_+fw)_PAU(~D{hH&lj&6_K-odO6X%S{-uzC!NW3d`_ z4z+=d%$zTp@)H9w^e)29>C!>KgnV4uCUa7A=hlqPtKK!A8Z)!fl94%4%l@5Rmtb%- z*Jid=6X-1JFd$lt8HG3ue85Lt_(k7|4pkL2m-`#z-kk#Vx=sgXO;*fNUBu6TQh z#QQ0t{mqayOmsU~8!c4?tV(_4;XoTVodek4H{}4>=~?9ug9L><^2f@8TiGorpD6_0 ztexC1Ia{j1Rel!IWL$cSFv)@nZRr@fE;m~1hG7X7BNc?MzDKSnuDFf}b_754GLAt%5V44 za9YEu)j;l4$!26r;_u}Xio2p$#u+K!<+pp7c$bRpZY!cbM%2sFq)Cqqp({>8H4iN< zCg09h0co-=p~? zGtm&shT|!grv73@k@d(}T`)F3UAajjSv9E72cL-PBiVe2lS~sxX{MH*?*XsT1-!&A zv8x)9R{C|rv5BtdxgIKn_QqJmdufB%7g`Q+>M#1_ArR4G%$nkw=T*;25a7^l|0Rk)QHV!3a|!L_ZN0PN!{(iA^^#8|c?C1b~PRlA!mBEM4B6!EaVmA@=M-@9mf?=;di&zT3ow-8~qU)%L4?M}KG> z8E70kh_d%~20fO=rxGF~FV1?hC9q`96ORh2R6Ri+V{}N^2L~4^ej|;5%9)I9-9mfN z^I^ub19TAD%QtR_HgCq{%&o=b4ImPaeec;jb3eLBRS7J{-;Ve3)xu!a65>M;Bm;xi z|1)tQiOJp=1-O)pEhlR>(AQ_yy6V;Z5n&h-`b5LormA$l(*zKn4AZ*1n_B}DnwAjT zMt_bu`+-=ke<8M^@*~{VIM4&?g}T+mCXPsLP<2$NYu;a-7gjwz%n?B~^amrhG~^yt zAD#>|N=jlpcdE#lSB;2T2u`TT!rm4CFoM`WUrEzh!EW!&VoL)C1aywjL!0@P{=>kz zO4ikAlr1LKPh_9j#nZ!MonA=)UO>H7$r$&*4Qxd6Ocr*Q(sxZdY&6g|Sbo2hUog2w zxS0%%be_c==ssbGK{!q^83Wrvvn;PX9rpQS2<9JrV=@LSBf6icfx{~=WIk(kUzGzm zRaVv}ZD1C5%a`-th-9gV79x2Y#DHJmXmzXL-*#&#sECYhoZt^#TL`1aoHLYqGvX-Afz)XUCi}*$Q=6Ho`rV}^G7~invkI>VRs80JgExc{;-j9DZ*4=d-_au zOgO{eigzdJP9$MnB_?S{37WG1|37m4?`Dz^U|bSlq_Ud5Q^#g^q_wz+zoac&Ev>1%S(}+#u$!gM*3Qb`-)4A|jT)S< zZ0)&28o~solcKNw@ytz81!p%hlKL?)hMQM4;-DxPY(Vs-%~a0aq&*ZpeLv@Z)PWA> zM3e^t1Ue04(I_Q(YPAg+sKJp#IIT?zUF>2rj+ik8cXo)d3(k8NQGDag_w7$QtW;U1~=`xBIlToK8cGfxrc3#Eu z5Su%yh_hX|sFasI8z@wXBahVMINwFV^cwu zN|MxSSeldA^=%o(E%_}8yq-@FU}}JHHsSU4$ul_<54nCri1hBLtCNI@!PA47B&&B8 zM*n%_F^DJhPgQCC2v1q{YVd-&i%z)2QIO~4|2|=GhE*;>BUIQ&UzUjf$Y$fT?`LQh z^o%U4;ZFVbSa%K6;VAe(AemX~V>Ero6Fd#x zMKk)ZPx;S9|Es{S*{0bNv(%hGbpU(>pL%5YDd$SuoKUzQFu{HAVRjCLoA%+F^; z@L4eF-wK|-Kre=}hk~OI%F43rHfIg!shWyn|DT)7JieSS1u`RB!pA@&OZLf&&lPbvhKBvD!6{8R=%&Q^6#({Ra9+_-v$#d+-F0s;i|GRt1 ztXM!Ogy+cDa1{SqO#=HE09V!N2~5({Ub4}z7R-&B12?pyI?VR~FuKvGE#}@n(xv6^FBm z)i54?6P+V2VN|pOKFnkY9Ocq9iD=l+8gjKgb7X%CK-$4Jp~{*FtIRfSM>TUb%m*B| z6Sx(tiR*%bE{_U}Ori%rc}J}c4KPG>9+>KbzAc%C{2pa67#xcEUiHcx4{t2IS{|^B z_4Fwa%dkHcu&)2c!%3xRc6L+elb8N!1KJF(*H`PQn_ujR>zk#5{Nx^Fy^OWODZJQx zJSan&$X@&X@Mt25Xja-(^VZ62sR7hNr^^oDsKVu-|L03xQ;{6zDrFgV2)h1srR2wV zpJX^m-r{nBV9WNC5BT`RJpILy>9*R|w#6YGQK7oz?y{92<+8F>|u_6b|Y~+h@i?(g1UzWly#nza%ai=P8CHQG}rox zZ$21%YfavP(>)zTzt!0175H;A*&tgg%zSF;kW@-+s|^cKGuZKe7=o3f`ou-|k?+4? zB|I1wctTlc0z^+l>01$$P3j5F{)OC8>fO<`AOWov-opfL#TcfHM0AEMLj`aoT#@4f z|0H`9+&QZ6z>Rm0gxHQ)+V1~+Xu%*bc1^Ko z(zq=yo=KP(9=#VrBw{x0fktI+=5WQO{XH{`s9k5g`#WnfJcA(8lq17$(xcfvvOF(@ zWlnph;fkvNx@%6fXqCz#h6nrtxT4rO2FCsK!0_FQt>94L?pI#$^`GxkQenLqlTR02LKZfvB95ie@2m*H>(~Xo?baU zFaw(RiX^~-Q7osU#AyjHM5gLys%PecWz2jFJVhyU^m^&)p5gayu>P$BIePLBFl2Or z!K>vbE->1@(|8YoCp89du7IPj`C$M=os?VBF`r=Bx?aK@XlCTTdOlC(izXibx0?|H z;LZTIgtjlH;?;e)MFzW9^UV0tVq)r_pMSb=O%P@4r#oD{oDh7B)N%bE^gl=}{y`Zz zhQae1p9VVYyJa5V4@}>PJO?IYQk!I~aN*%N_V!Lbe+G`0N_*p8Lh$J}watB!)CDxO zc=)mm0>H)Odc7aGM-MeZzAdsd+Ci47i=YFu6i=eLf0`B!)I!}AHuNxRJ3o^wxebHF z9}Q5~%8+amkUQIUl|*hc zhSB&G(r7y3^z`S@XE0|Wuh6Uh^_#V&>~J1^*rks)Pa>@8?ngTkFc>;?r0ww{&Lt3*pvb5_bb5H(kl_-8V2iHFNi-&)M z4og%HJ=!yDnKdgQh|j^}jqtFp4;kARkkm;VLgu;Sq#=)8ev5OCBQJmdT_AA%b7J)e z&ohp1V=W&smI1$B9}=%j1urHEfYrwU%FqVCUY(dOf&MOu&vweiI@$(0&zAT55R;pK z?LFq{yu}Yip*26_R(RO-Y7GY_wCaoUDwg~mdD}nDUwrf7bYa8Fw_yvlSP0L*aJ;m- zPCwM)kOuc<`=nmKQwdKP_Avv9rzE%TU1R=@3S2#^aU8Md7jns;PE)-#2X9*f~wl zQ$z`L&WR@Xg8vCvBvF^Q7A)K3Zo3?q(UO*kFO7FGux?pi97w1O9XplnA8#ibzd7$E zIGOBgQK$bLYJ=_r2xjcQ8uXBl(=EO#yd=OSW_D9hG?G2;#Ma%l=C^a3y)x1Pl| z6x%v$HmlYw3yeq!o@3KwqFCA2=K0(}r~ZC{)}_f%a`r86eEVTB?;tab<(=o>!<82s zZdFhP#t86rR-!c&k(4vVoFx$#3{h=6RXqUB5Vx}?b6zkpOIKrad<${x66~UaQ8CPm zk*nJl{L> zEwf#@xJgFdOsW@B37aH4PR0vq>7|%cI5`I<3uo<6s=7!P(ZLgR?76&+j`rmHW=(F_Q(VAl5!f0 zwKJqsCo}vz@)Hbcu~mT+cSnt<_N;kW4B=L0cNY6Fk>f$o^OFBJ&hozzbN+Xe)pI!H znNw*+R-qh6alQRO;mpq6yC#>T-1m-PSMMa-9|}+F|6wehSQ9dV#@hi4=W~z2dEb49MI>GZS8qZ*H`1InaN0Ih+ zGz=6LuQjA-QDihu@JN;GD`}!_>Jgr@_dYn83)>k(;>Z|=6z-zo_UN%$fxi96-<$XR zy8&Z+SuvRw3r4S{vT^N*lV*L9^*AJQ$cL20%(5}izO8MczW7e` z!-?1hoV6X7xVF}^wwgILo{{pMVveQRL;tJ6ZR4t$-LdVkzCApk??*-vw^y2PO#%9? z``|oScl^y(>-mM(?`C9B17DME&3z0L1U$+n{2ex*-pW!8zvP2C+Y4J1BMGDG6ZnKz zv|D3Nh367sn-^as($o;473j@S3&jxb0VQlA>IVj{*-m;_-57K$ z=HGeE?Tgk@iV&x&@|ict_~!n-cvNn?P0kL^U3|3|*Wx_f$gHibAAqUkb47vA^)v8I zJ4aM>OfJh6a|=zfdT|cR2HP4BT)F}(~?V~wBy08ww%n#ZgY+EVKR_@O~5ATxY{%BiKypSC_lK6 zr7yX-HKWf2)|BM$CrS(8P1u1Ihw1#p_$T_j&C4o_|6Cxq&(YGD>?~detL#Ktde%<{ zi_M}=z$ly6N}lzXx*rkx$D}{!iCd@QabCftRg=q~#l^PmRb#;q=JJ(_7jn_byBfja z`36Du>kYj_jEw^H9@&ncuMD5w+T~W1Sx*FsFqB30`%$ep7XuVx@a2b%x}DlYXWs?d z_{8Ez3iES=9YFH*jyAPe_TUFp)Yad^uC_NklT5*lGw!AechN{~JUHG#x7^k6PCgqn z)_d;w4mbL2!#u>7DzEV9eb=9`FmqHdI{?=!!JGC}ay~eYvDLjh0iH6us*`&_3(Wh{ z$>A`g+k?|wpJ^FuRxL3pDt@vAQL2#CrY9|Fx6ji`(#~#ieBo9upU(a6;RugbmNt}R5oa#DV@`GXa{UeX)9(q$iXbyb z${Q)^NiGR-aa!orvi)L*e%$)Cb$22ZE2&Z3-X`{ex)R*2W~KM$S1Pq4YVOMmxC$PV z-|&!*Hseb${$0#Y~tw4pz)`+Vdi_ayoCKcIl`wUv>Z z?MR=nYC>iak_(0XpugDbfD9#jObQ?;CJr+AZVu^rwbL-F0oD73M?GP2t`P}=P@5fVH0guU)r>0XHmTR{q~CyaUVa zit+c=>%A-O>tjJ_%^0nbke07I%;L3)O4@g{}RBN?JSPE6l^rjU-Q=QA2WCA|}1RdA{}5nLcW3E)&O8wNX?I_y%@ zM-jicL{RKoJ;3i(g`4)z>abQzMEWPBV~9KFxqhajEvvY(;b}sLPD7)Jyv7EZmuP?5 z34v3S@tTJpM?oGt_1pH&v=pI(Lma0t?a>K`$Jw4Cfm0pZUq1{CUL4)j7sodR%pMOx zim31jv;pgEr!t4@FLjz!V5)?6VzLv$5`mA>!x&{)2#*9KSxqMg}Ig$p^57yzC17uuq&E_cMcrvAZezGnhtRg_4g&4wxwzq0EAkr~KZA2J?rx7mxUuU~|`CPSylF-XLLvZC{;(=a$H|uTW`{;D)pKUY@ z#affUD^K7Bw0S7~2-H9YE5W21=(cytafub8BIFJ8T8uMX@e^jwdiC1h@jr}gnZVG@ zUL)48O)E|{<{b?eAKIFb&XJ6Sl{@yUP_`wTS{BKzR9^XHsz1pC+doKg9ZS%NF`Y0t8pSbxxXwfBXA`hL0T~P* zn(Madjg$?MQ2FmfMinKO@ADtN7wbS%Y+VTnw~P_bHslTdB9EpV4+LiO1SsjpW>oF039h;^)A||Vntlk#%;7FC2@>F5*B|^$XMU6D zAEA~C{)Rmyv9kBgguuDxVrJrim`kqT+hQV)Aa-b+aa`-1IW9 z^~J?<8)Er_^JZ)M{NY2AuUaqLR)3#Y+ZN-wlIv3!e!q=pW%FHO3jYsd*r+&4%K5mj z_CkzLeryTW`;I|HkU6a>o4I*DpxsDG`~LE^K&Q7vEKE{bZL;yvm1fE3f@Hv zU@-?X&SZaRvnt1`kjr&U=43!Jj;A@^2ltF;+M8E(qHEq>qO+`2ruvOJN`pe z5xe~KirSQNO*Q@W)X6X8co?Tb2ZcQ=eQ{9j9P;#+{Yj&3o@(51G$fBgTZ-A&Qp6=l zTMKN(O;%_lUS{n(U;9V3zS+qjUJF<%QHls4&f$YGB+dO&+m+Cr^xLSrN>95sN*rM^ zs#|O6^3#90%=wYnom6dC9PJCnrcHBcoLA2j#BopB0g*_>YD9BnOC|Lj7#WPO(VKEF z7q>}z+r3sukdyQIfS~?ed7XC+CiHa)AtLH&Clu3|4^x=Rw) zLUa)y`G@?giu1WKIO>{jOmmvyHhkG_)a$drfxkh&4+DI& z+htX3lgy87{SpD~mYNp^>dZ2e@D~iyY^KA!m4VWR8vmz`v;Xgqf_al_*10U*1`o3P zawqpci>R^qKW1(YYm)??oTD^%rf5}eW=Llw1roMK=>PymlLtmpNA;YG-%9?YGp`Fr zTBZV`F##?%pa51-U`jSyPEuEI;JQdd@I>dAL&K!+|6$m*&1une3H9?~C5vL7-m!;M7T#!nN^$`#;=xXAGBr5>B9X9th1KFyY zz4S5Ah*I{0<=_*@g}Vr`;?bK|o1J`Lp)s@|q-R4JnF)B|l|7_3qVR?7W0F~5K*wHI zRUyf<^so+IytkR5F-3!fQiP$*T3%X`$VIhTLff|=Gd8-al29}f1LHU<6qPWxmsLu zO`1#ltqWd=ewT1bKs{tx@0vN0` zCMkIDH>BN)B3C~Vy?p=XE21)|G~>JaA&;Ubhg%`)v;P-7hP+Tii*~ljgNMP`eqPcK z`fgEJ&S-)zxx9ql4P5koQE<2YZB;hXlx2!o_(Ker3pFq+O^jV>KG+qs+-{Hnhi+Tb z^qsr4kAhqO(z+0KuwaFf7T_Ur{G}=rV=u9$K^_C=gfDM?a(Oq0m!f!jHU*KG&(-|u=gof@fup)W zw1t^k%yrx6>-C00etyLm{8MITipu7W%~`jXejmiCI8bPnHZIBi{@Bv0*jGW<)YkKz z2AC<5W1M(MhKH~74Z0T*A=tY=Ui#%es z0^61X?rZ}-q4iQbh}U}1UM+`ri9g$TMW_NaI0_M^7C$YTZ1V)bwS=9>bLZZ)3n}&j zPcB@Iz*({5!(M%NXKOXAQp`&CU+*xD(N)1}?MaF6&l&q^Rf+tg1vORcJb9D(b9yCy zB1P|K4d*{{Nidz_Zd4uirtU<_j#p4n(@cH%z|bi0>~LWwzEsRN<2+DyEskS6l6b(z z<}<_%kHfJ#VFzjh78uiOIbY3HGqryWP$5QkdnGT{ju?{zT5XHzw(TlC38AH+^Uc<~ zfIlT>T+};s-#3ePWW%bmS%zp!W|BEnmOB3MJ(qgZ|1j&O= zHr&LV?OGT8Bs@ZBrNKPrxqPPSKbGKOy*C!DV&Yj_`I(iR9N*api-0)5z@*q@ zyP?gX>@Gk}=|P58pkYg|e>26B4mSqfZ_Run_-9Gv1-Uh`PotSji^`psp2LkSqrFsM zcbDD#G4t;Bz}s4vu7nGSzxMhM-$TjkO}*@~D-%gmGf_|T?fu6Nvj83+_~M~K3c?;w zo8&t5>Ilv~sj_ZtDR(5*oWZ@oaQv^GY@qdz8=LrdVxi8hB;ftCP+&-RVvVbo{}@mvI^+|N1CO^5?Jtfx!UN%a4Rv90)Dai!d1=e$KvM5 zP5!MHxcyOT?RSE)nvS-wSFnU^q!TrM9iwMu!jMSraow$8%P?%r7M`cbZO54%?GB2g z+&ybvehX2#N`b4O_Bn zh2jy_6YL&#M!`A9U7yAuMioyo)dtW;n-N8^CdFn=M>=u0pIl(SfuS>#A<>abT&d&- zRfv;%Q@lf;$&Q$B&b+EOXMXZFReQc^JhsNyc+)r0!S9mfYs6Dq%#ZnVy$xDLqW zazB-SVyxAV*DTeN$ywG2U1!!FHVGE(1**4TCw&Rcgo*I*QZy{;pZzZHkU&m0yOxAJ z@4tL9H1xN;z5F2rD}x6E z$;!AGuf454*9i5e9pvGQ*mUU~>hY4OpwqCLN!ilfr58I43=yy>6ob=Bd5oygN`(2K z;=}7AmHF7!ccn*E;12_# zgo>U6V7dZ#0X?Sc!n8}4#$}KOQ4?|k64n0=<%0KGx|ROLRE4}bU7D)Ga8;Sr)T?># zbjsTSyu8Tv(jU|^?Y@X<4x&9g5 z78f_;fvK25yx~dCk=Jmu;zw5ATE%Z+V${c@7w=jWUvaPrz5cOv))ZM*gN3lUFtP3gBw&tijomw6UX+eFY70MSvt|dJ(!R&$X`PNX$-@yb$s~V!y@l; z3pVNNROYuOo5#;Br*`oQ7I0Qnq#H95xT5v0xsX(1cTP6Koc*6?{{Kl_IZBr>DD2nAo!KH&Um=!bgxH zlWPq=RF!aIHxu_8;A*sjdn?8A4lt`@e=kdu0Nm4sKcAw`+CWMOSz%QsO>X1se&8rp90q9##>O4Uj4U{Q-C=yid+e`e z9yn#wmPoh);nAPK>Griq@3A{Ge-$EZ%&%E;8K0KUu;iZhFg^g#AZpzL8e{K7giqVg zHafmUB!Z;U2Au`jUB$gAkg*N(rU{NqFj$#FsqK%(uc?SX*h-ts*fMyGN=oj&e)Tn_iEAJ`69+r zeWAkGp>*z6BKfaszy9?p49RmEO)CGGXqjf?&1?*8iy?ui+3<{)T@5uWZ7eB4ukCF1 z+emrc)=ql$c_-+2!M#A-DvZmU8rJlL*5MX<69Hch6V!+gfeDSmOHe@4;Tj=H$bT42 zPNl5clANihM-?2)dlZ?^zhEx@=@Gy!7x>)}pO8tq;9Q8V?}$k>9?+&M1srOWE^*eN zt=di!61M0 zBE5BF_~5!S>4VlBdv9&3QCaIlD0g3c99xymo(ME>B6i%lnRr>8gt>YJh{Dz*$~FYVR>#(dFKaE~Rg3-Qa;*x>A>) z35&t;ddZeTd|Pr~WSoK;S+pQ;T{eP^%(*>Y=qgw@$$Jbke50N^=^XxqspA9OoCMM7w?}V`iYERn5oybvz*a;x}5f>z3^hCO`RAmE7VmHnv)Ip z-^o%t0;*_p^M|~Wk?B7wdw2w$Xu}2~NgwS|Z`s+o==y(-Akc<}?W|!vzmkByZxcs# zY=})WStCtAbMaJBD{Lcn92lTJirJU6`7tQ}k|Il|Ty*icQ+9TxOFX9^;&`O-yf@&J zi8Gh}lz0keaKSJ@ryLI@akR7)&!CKZZJswOHZwYVqQ~~TOt7so8p&nBTCGA#{J>DO zQg5gQS;%j0h)-{MkBLb1Fax~ z9?x}@hfseZaz2xi^xZw9ldeK5cyD6zrXO)2Qk8qJYuk*~g=kcD-%R<1?lQjmZJS9s zmkh75&aTimYhxXi))<^?EN;eWU-G+kim$Tmjg&R9``$BrA8f<)b-X0S>!R5{>h z>+W{W>_Ojz4z;@vMdGcmO~Wx{1YaLtC%bRRO>5}0`f&@cr{J8404NXNxlZR>7Q!bh zPZy}r7e_9J)nx%hsYO7ob(+gr5o}rpLy;(3u%iDjXJ>haJ&#;%eYZphc8VSwWEh>M zo2Kb$*8X@KqwYX}P_5A${mf@C2o!o(Qa`I1C=PEKl|?M63{-ATf1VN3%!~eEvdXZudf>?$Sn{Rqv^14B(?y z+4X`o9YhvSwB#bRAkpflh2i}>NVSNvUH;8467nVz}SCX zLI~-YPW|?MrQD{M3fKpmy6AX4TwWdpuVhgt=(G$QfD>wXtGM*kQ+~Drbw0^BrZnBL zq`Ka{rd>M_!>dIi8Y<%$x)YWLu*Zl6+b&}ymK?>GS09d;`PIwJQBF?e;78+ ztHr~q%)435uVdwPX^G$uC+R0W8_*lJ#Lt0hN#>-LTH+BEQ)@^M1IGlD^;duT)|fmi zGu_g-Q3*!>XwY}8A-uVuiU8Lqi+_c+##AFv-7?g z7qcX(SW-kI)#WP`#|=fIp1^0eVuJ&s3PfPxLo8{#Fp>}vS!9clk~n8 z{)h1&hR5Y^TaFh_D=V*O%N)rt$0{b)Pz~i@q-!EDM@40HLWb+OGz_giJyOvGEZ`mK zI>FA5cD#EA$G)pp z!M!(P@Etaq1vIcw$x`)OJleTElcTtT8 zpBt924#`PtG9pP7<%0j8i?I$3fWF_~1WKZ|B){ff2b*R558G0sSLb0pjq)Pdp1zHA z>Z#;YPJOjbK6wvrWb9*re~-=keor%1V{v9YJ`P-WsU_*+#zpg2Bbwsb&%SW0dL0;) z=v}6yfkrq1aGTzaSGG_Dm0{M`j+uo~=Um zt>xBrVzk{2?ZchV$BG(rH2%^k+yNBS@Wr265l0DE@OKgZPwJ-W4ckYdiMAc^`F2N> zzC13!KA@k&2@3R!{z68yT7lRNnZvuZLi=9H<4EUssw8D&Q@L$PAeN^I7%LC^v@Fe6 zcRBp%EKHy%F^%L=tjR)xm47YK`i+t-?V(gjjrLHFu`LYA>1ZO)jQb}O^M@{?!a1?A zMU^9qCo7jro!|T=fp2c6ukDTQk3!`wx$DPm2fgm9B$ zj-h|0)MCo5VYDGvq}#-ze|=b2f4YY#&jdZDuISke5=kSu!8~ge9CW`f2YnUvJj$%u zPRE_$pz~dfm)d)?E#WFILTr4VMP7WPdMPScN&H@451rohBvJ{&cnmt$rgy@=xfExL zSNtAUpC!h_zLL1S6p2{XP+ovppZRiRWV6GikG=U=i*KqW*a5{xjTn(5;F)1`-tJo& zQly4X4V)9ggYBp>=6lXn3H4FtG9AL3dYHG#rk{>$^m8ZCTN9TUXr$%>q}}6_ZDRmc z0@~?g*jZg~DW-NjrjoNa=NNB2OZ@6i;F}cLc;wUF;V@mfwBg8Ukc6_cRm^?6q*x!-4KcAJFS=ow zPUq0Td9xuhUjhPBuKvgj!&e)szo?}HY0Vg{Y5KcjX?5nP2UKwlMd@N{2SxflR<4x@ zkK0`G47mV|xfsJaK5>@O2-blms#PcY6l}0L3e>cBf|hjH7KFILg~#`cM^;lK;+01q zxV(K7V~=0F|2)3*_9w?mb>6!%x>?K__89O=QV)iPX$B?h<4+iM{>Bj zLFh^2VtBOoDr<7zj6-T4oMV3`4!Uwhw5I*lI);==p;5(15euMtiSUC^V4BNUBe>0e zIR|1f^*;=GM{Z`tP@DX8gpAH=b(_&`WWnc*UowI1@YYyTn=z%PyA))+u8FoUQ^Eai zMVyn8sZzLxBhD&Pr+uVFppr16Dms%_mLojh>SKy~&85^;Rh=Pii9W=xe~X`v#X)%8 zHEGBdZSH)LOvyZ~G0p`(e>IMYLaA#L-*GeK{k7{usm+pU*x6hDsn_x#dZ2iS&MjQa zp^A(s5c4n!JNBEeO-rzqf?{QV7w=^{$rn_oqOR*o=j3vIyL1DY>aZm0K5-75gVyZz z8;H&fXJVhFe4W0zLH9;Dro}a#2qwFQq)J^ac<}XYp?wa+K6FV*(dEds&&^I0jyXmZ zb~{`3G`0uy+-puyzUl=DZih7*ofy3$y$$Mv!UCDw3oBq|-2_t7RKz(Z*$kbLR8dD~ z_un0uTFEfra!46{azeJ0QavQl&e|c|NSXcX5N%oI^bS>Wg!v3sMspyemFs`@Ii+<^ zSV^3)rfBLACJ4W%_9&yf>O2jXmwesZF-=MlaO-GVUWDmfMGnEJA^m_&Ksydr!VPP; z->(u+R9(DdvXHRWuG95{w-mu~>jR6T8!rd{_X_Dvxn)TN)>7Xq%jhH1U-aBh2tm81g914f}uiQ;E*GfK690&R;>nbCEDw;EA9pT1Y_ZFFm^ zwxB+sh9Os%6Rb2Fjo@GdB>tIp!luiv%FKW|lmI1}5MY*-E#*1r6_j~3u$(I0nr*xWZw#lrL(o&yC zLk~}eyzZx|b`wMPm1AbjPN0NU{>O|;!n6P#MVP8yv+s_#m)6Ws!Nt-r8KUlLg6qu*-E8>@89gtQVROa{`{M znr40l>TOx8Xn1Z|`mu_N4AI95?G^ujzE&rH z1oxsXE$+cuDAM9CA;BGj2PatZ;u_p7xO?&EQO^^Y#IIdT?lECAmDBi`)Pb}L+GTnoQRh>j81<4d;2IqY;(iH7o z?vbrWnp8wozWMQ8M0dc*_63_NX5X^7;9K{VmW?)LWS)i}VT{ZR39)I1`hHNVU2HVs zLH|N{oo&pl6?7<5o?!q$+G{0HhtI%f`GZJ*OqfQHcec zZhc(v5B3#Vh1-N`a~c@+UO#w2O8COU- z6kc_!wQHo)#do9SQ(7PSkgR(C8L>%eo&6f7(brU}==%jzGbA>vY4pn9c-E@PK0#>B ztJOw&UxnwPMRz5eTFXRtcl!;rMC!|1zv_QNZEU&-yI51BfD%!sAGHoM`TNSweAGMR zhftB|P!(JQf${U5N{}&-`&xeE)-?RO`0F(Oft&plG$rHUHS~!t`tXhQ{%%jb)BBWa zZ>KiOa7^z(r992bRvk?r0T-(&Ja@YbxIYE2v~jb$7m4Mq81sq3QPz%tI#-CaPW=65 z;6`Fi7{~zuWm85qWB_@#Byfr00 zY1lJ}bf{@>sF8zRK6c%DScbb%Td?oE5z1ze91s;J-)!OwoX%!*w*m|?Io`ro>jhNpjD2w7b;TUBO6b~D*F5ScTB8%_V^QYYs77& zQ=l1#)kL8**MHbr{7u>0-oY$tBIx&zGOcbVi7w|33m@LL4lkv$W1jG*u{>SOv=|qH z0rPReFai38srY9qKuVTM`(<$t1t&suP{Oy{LK*m3r;5rzqUCN%!w`wQ7cybQ0UbC( zdc!w#k~>wSRK|oKHFsuLYNim6lx30nC$;Y`v=0YCdr_}q>yBUbGdEX1Zv9;wzKN$c zD#;nESB@UMO~W0sQ>Mdezc(EJ8iqCEeC@D?^@VCn$!E`!hQGqCo=_7mE#SIpmbXxZ zvE@1S#Jy4a9|jZUrGokA@QoPnbFa~qQl-ce3u#u&_b2~TJf|Z_44V311sea~it!k0 zL9++{`%j;O*jUXQ_(5&N_$@JWn25-{(_Qht}U4& zTbS!t$#fl9U0@QR6C)#5*Nptbb;5F}?^?mI8j z`g<{SG^;y=MAr%%rI1`_3tWfViMX6Q=8#WzPU{G7@1XmC>CIo)tdc2 z*kU`3FPF=DW21T<{7lxXbKsw#J49-Nqeqf~qg2%8`-GQug-*AN3{Ofas6J3iGJw1NGu$C6+N{#b#zm24z$L+* zM=5p=v3fQo9>y{Jhn>o1Fy#p)et}Yc+wND zMJw89Hky_k9#so<70Yytd7n&$3!35!vj3u^>@(Ta$9)V|>72`$6pSSc_SDz2ZgC0p zjyEB(&Zb9k?4ffk6<(4KN%`QL!8E}J8lC>8=*rC`Fd|1g?< zTw&3)9*`w-8ZI#1bYAw8Hm^(NuU}WH;Y@yNR&~d9c2pYr{i#<(JP?~_TcjezI(ogp zhPCe6c-6UiNM0@OgRiHU_5^Usl#w8_Up$)jYNa?o?!$PKLVVOyc|u9WN8uYgeAIJ9 z2GP}t8E;@@f%WEM&5Gd8S5|u8p=ekL8=Lr}Qf@&x1PPw`j;BAfOIufW;8^Yr-WEtJ z2N;rHGa1@;NRd*g+Bj0h*@sBzoErobR+5lrhoi(fE6YBx8rVlxQxW zXq~GbU)Bwu&)}uO+=8jc3obNhAwh|}v@MXw`D~*&*D=4#kab(bO<<)OXg+j+vaLg?`mlT12Cb{_2o8TSeDm-*#Y5XQz>k?N(RuOlCLPs ztgxynJ%o^q1#t2rMU9J6+7{6;%IIMXeD4pjdO=y;^;Yk-xeXj+ta|(JYE98;&X%vb zo?J|+qjmAwv``$4o4I)5y}h~D?&azVy_dGz>1wT0UM&*0GZC-5h;mK)bv1KE4fNg- zC$@i8a^5b%W(w&1uGY0wx7;ng0<*n!mr#|QXGL=WJYOm^(3||i+$BNGku)$RxU1U2 zKzFH9?{^)%^4isqiO$h`kBUQ)`W4%E5K2!ZGS3GifBfI5i0BJ|Xk`M2`FN!InO~Ba zStEsw$w;y4KGYaF%=qavkWR@SZ1~IyU(P!DFyle-M9^SiKVaT1w6U~5}IT%#4`-&{9-IC zexC8>lrQ6_K@~7#-pD7CAMwVbQqU^R49+RZ{M_7<>$&?4gZR3fsK)opa@cEkFC%~g z#rSACzt0wv!)=)9_PGs{eoG`U`UpLJTRfo|xsVF_*rgkpGWk0G^l3==pQm>UoK4rv zLRLVc=-;T#U;^T{$0nfwo=9T(bmZ%9Fn5T!caBlW*Y9%TGfgJTWQWLz8qz-r#H(Cg zFH~u7EV?0K3#Ie_LX$@<2=&TjnjZ2s#ULsQeRMTd<%D_gKG|2r1MmI!nYqm<-6ME; z77l`b?@b)e?9MQ~T#Agq;U4UJ+LsyaOL2;KuOg>2lwx_mIa{k@5<4p6+Ay4xff6S& zuT^47o>`pgeMV3JPf9^`Fl}FCkw1Xy{Z81R70bsTrEXx(W`?y!-1!=6zdf6r)yTy}q9B9^OBXsh@A~9Xrkjx2+7n#pq?{P?{-8rOQbQA} z5Pm`BSYbM}NkYsm$~2*Yt#R9{>G!L&XhipLJF{N3 zR&G^LVLBydNWIxGhCt+-}2c{ z0<5s-Q^-h^ft%u6xKesCF|I;tgT*~d#{Q<3uy$dRVcws!dXz`W2E(mY{q>6!#t-0E zM^mq-nHMwjz@A(*Hh;RS(zxJ?Dg&UJ3=FBJ)$@venDVURGxZ76lGnoMc3`+8>+|5C zZK*(5r~W-NdPsDQ{46VFvRKZMMuD!(&1=qpheUA@bT^+^KblOGilA|oa#aQnDwp%$wP+X>q}rcP?93bO)%f;{VH{J80%5mbbg@}<;{IJhe04(Ir164 zS1-=URq~cpH3swlnFYgo%<~zA}EjEM#I*Pu|apbkf9;l1dIG0Fj4tLEf3-{wyzOljy68CKXj}ks-lpX7@4`x!@Zqr?bSBYF9^;{T+AIE54+?&ukhuk_S@w zd*r0N75yG5`@71FG}CB959hRF=KR-%E9Ok7y_eE&PR{oSTVverBXNiTu@)eAe_g|2 z$G$pRv7soFNwAH|?Sc$yNtB9?nLjERw2<=j&Y76$EG}1QbW;EEDPR=Pip38{ivp)GN%I&j?n8oP;slG z)6R?L0k0(cukXBsIWNIS*2!l;6xha|$tQg{>34XV0`s_v4HBq@|d|iwnpG~&0>L9oy1?LGY zy?rn&+4xrCCb4whN-?u8nT+a_rBt<7mRQO!k*Yt`1w<;d+H=5E*g>CgB*WlJUkYY3 zr7^*hKKkJt<}l8h;NmT%l5+kw_VBUXF>$J%-`axqqXaMgBB2Gb!S0}|t)#3eWK>fE@ zQ^m+uBN=tNT-8xh{5|G6@H}4rK-PmIRWy`D(H$3Sr5L5IT;m^E#oWZ}tOq*`%s^Lu zX8853D44ib7)`8AKHD{FCKpVAm>t9 zIOS#vC(1R>CaS4GK0VznqQ`Ni!LcKn)sG1yOngs0Ft zolQ9;3o;D~XDEdml6@6&i=vP<^`ZP5+?a7Jyw~90M`GG|+gbUQzsTm3WJe>qkU?np z*X-?c?g`U3OHN!Rtgj^p@kJQEx@kx%sm(^$Jm8@QRyPkpJJ%6o4@&Fxt0B!`r{*mJ zgM&cmaKDB(m7S8atk0A8BDT*JuXXIFjLE1dp=LAp#(9oUU>0=jH5-|`<6m=6G485wY#^=S>*y%I2bY+zE^r?2r`lQK7%4U2Lw2lcnd>%Uk?~u-~h4e!&7e659^33F5gk_g_Bv z^@Sog9E?_6f$YYZPVTUeod;J!$boAsrKCA47<^`OFsolY5`aJemGYgPw^#51lkGFb z1?ulTVIb4Z=SP!5{F8WA_k?=!;QU`ck&yB-sX@<%Wf}^;*vAp`I?l_#u9YiP2;E(u zw2|iB8h-mP04g*^J2&1Qkt(E6-r|mYVDZ)?%pHdQj@D;W&djTQ7c;+2#4MX``7Vy& zXK-M^Qd$8xP9B~_mTnIx!~Vu5W5F_5jZ_g2Lij}M>(<)}DZFGU6+MNhCJbzI5h48i z>v_KAyPS4M9SYx*IsqS2#Pn4->-l~eG^&bTFrtb~qiJ_cQ$hD}*2wH4B#1KjI+k_B zpBvg-FZPdG)dRi*AQGyMW0%=&OIa-e9LjC|Ku^?Z_=H9AUp}an zWHSZ%>lV>F-6uMD zEa*hq3Jzc5od~py5OX^a(^V5J(zzUdUN)4?O_-6^Yhvjt5N zJ?!Uy4|#_beeoNTID3BQg<+=9FepY}uQ#Ay-KgtgFmw4h!{AC+gQxo-B)DsiiD3bF zPUz~j`+cR_so?g*!Huxw??newsif4indx2}-EvccO(uCNa1Q^gMeNDFw9Zv73i}v< zXSID)%r^B(H^ES9>koJ!(Z~iXA!%;ABT@FAnOzSHIl5>6-FEqbb}a$g-D*T+Xq?P_ z9$%mU5|DsjVVdh>g1?iG4p4I>GTW!ET{^wDn;&>k9tSsmFE+1JW7#%Z+Hown6g@I8 zl*nfEW{B0^*zMijjcm3TjqeV((`2RRa9yW2t9@v@Ous__4|hlDTy3-m#=YvBgNNe> zr$VhdH9i>#R2zt`OLjc+`|fUrF?#^tV_$6F{?F;KUnRmQS z{v2fev)cXa*i&t!zv9O@+K0pavya`rtJWtsSL@y15nLkMAILRDC*tdS6?<6eLI}mz z{eA}j{!FlT(UXA6D!yJNN8Q~4T!KVy7o6r@gPg_wxbvbMwoV7;E__%j9)G%IwzbeC z+9Y$OT$-Tfgn|tX0i<>sXi;0@7>Wd}r&rlTd3Rl+jYc}h{bV}}l1)u(6Blk78h^6- zwHZGV7ku;l94;eychc^hdAy8Bu#Ukidr#W$tN?XD$BL}R8*5BDRD;B?FORZ;+nLjv z^TEx9Ur_tXlj(2ZF9qOK7C&DYrkw)0XGY0hMje<=_2aU#={&2#4-m^ln^-?jlLrsm zbbK;l*G)MuF~hji&wm5aUQRLm?1ax|#U!2Go#AA{W!rk#J=`c3@;oCHT;Y*(GGroR ztaxIq7@)|}8RFX12Bb$Q@fo<*6U}|^yDA+3d|-qVIS~=g7h9=(XK-M}Jvdy%^)Na3uQh|}e+>&7t4mZc1j5&tRgO_Owq zNFe^6fy%0=RtFleXATXB%NntG!Ig|YAeLxdLTWihULlv9m%Xht>tKM9K_xa;@heQ} z$NRMza*NKwNUOjQK?h~BaDE0@gsQIZF9___vgKV`2qO|=Ut9&*P(^JGP9%(H)dRoh zK*?P7xgXCFwvIS1CByuS%2fN>|4vpbHS6swjJcdY>lp#-xmWpaYFxuojGQ{~U1d5+ zjFhbGGX)szg9r+B?oUWN-KpBI?>6;{VNFD;20jMKK7Ki4j$AT(Qh0A**kcIqw#>HP zhF~*e?&^J{rq(BdZ%I?4ZfdD2(r40hOn!X}2vsX9iV5CHxdcqvIDuUa{g{r02HViG zS^^sW$Oo^Q_BT==M#VP&!`LqKkn>L!8UGzsA_bym>VQ^K^?bC?kK-OLC{<0E^;x;f z=T0+Lh?%8qR5blUsp{`+_NRy;7aM!leipgEITXuRID#X--nNdd-s&m$tFDf$O@A^3 zF*krMDG9 z*;SwOvvZv?HdJq-BfKC!ZqDBGpZ-N`c^OM3k9Ky&N8>(mU#N%Ad;Qj=RraMs5IP4Z z-JEjRI8PhR0=nGOb9=1%yqsCeW*YGX&G0ymPj!no0aD@ZsLWNqr}P30wgWf&n>MwT z9BKRT713zk$m3PsaaDCzx7=zZi)7hMu$k`R`K@l9y2o>FhoH)&rUyYXD!kR|-rlD3 zq5bdcakV2TeRgw56akFwTaRG~_*pvDJfN>~wpEc+2s)5FlAgrc6TtL-wwGQ(u8d83 zlMQ5lXXpWH5>rY@1BxkDx0{XTH<^cF znKzm+udF~8Bc1-jW@f5L1;&5xExKshkKRZT)6RcFEL(NRF8#WXCQ~HVvcD)=_#hnT z&O=7#^p$W0ZAji;Iu?G?*NUIbM^1Zx)Tl_cd~nj>IG1j}9Nn?Xbgj03Uu@54qeny!!^p|`zQyRA z*!H&iie&0sp`KMTwYarV_DUg2iTivSG3$}BWX0w?Vg0KP5fJPxeV>4M^qE0=6Cxso zD3REiFn|3%fHNPiR=NL~Z}9zZoGFgyB8C^8hc(em0pVNmB&eism9*7}X z`T{Sa%LBnWK7qV4)aZB}yL~FotfKiezkG70XI~PNct$yurO($gQ5Kp&=dlpB`17EA zT&P5#WIoS z7P@4X0*faKka;}pKFUp+`qqzDXl1jN%9f7IB9>%Hor;3?1Fr%8t0Ue1NQqQ@;+-2m z4&ev|MQ-lrKdh9JCnst(e{vo+CP;2{JF;~ZyqVwts?3{AlT}{{&N%WI)r53`#?kDJ zcpTZY=%Cr09_zJ?CNdp6?eO@e2zE@y#{6+2?H;b!;jhaV7&5@$OBAi_Fa4)|W4orw z`(XyN5WHbDxc56Y8kt76a9HEvfwOK9UbP#(P^r2mF0wSo%x<`o_;ZtJJ-w3gbZ&=iEMR4N)+`CJ8 z?`yAPXv68w2K&+j_lLb#{LW_#;gw4iG?Z0SIr+oT9nt5kYn%9MvngANSa*`t`c&CX z@9-IXxleWFgnPnt_976o)Xx{MxLS805uecBMTWt|z?b)%SdB}Uasy*r=&pNidf$t} zaP!a`rbGsH$+8=x3Puh+V@9rRxEqR%eCrAS%lB;+YQg|g95~Zf;muZTs(zFqsqK)Z z27{}TZl+7g57}ZhqiMiT}t;StG+|@o>E*ooHkQ?T2TESSe zL`>Xb7Yxl!<;2e^Pu%W&|NL8#GqmW+7X|#dRN13hL+N?rH%;+2T>B=oq=F#3&bWXn zfcx||LPwAHoqOP`B@E#2=UBf@DnAhQohdk_{&7-GubTjt*|7A4*8@>Mjc*y5?3wDLcNlVLk0x6^6@UUo zNF{aKhSt58b;l_&?xttV?n4+tR8#_JX2;#p<5l_6tp=E@7n(`ik&N1Jql%JTkrT*H z3B+>%Nh}31oO$BzjmP;Nj0`u9B9YX+F`7M+^d&#s3O7v>xL-i~h{-{kOrvrcsIT5W zk7u*rVuy8u|HJrhts9+>e20|K__O!(fV;&V{Gd})WaKx^h0AgiKDtRoTW_uvJ*&XL zoLbXH*C--9lrMPP?tD+H-P=Nk<5E?AgU|X5av#^z_{h&e1<+0G(^oi`nMlaxGQ_fJ zl~3C6PIcDQr&05C9Gz7C4H!(4KH zIlZ~rL!)vpPMoPNxZc*{KeOR@YAu9fYZq6rU}wDQ)tq&4vF~OUzvn;mkA73Ov2kHN z0~VyIP7C-dbtmuH|Gbp%V;Js#81#%bljP4|2kqRp7s&O8UA;F%A21)EM$Wu7iPpJO zMQToG<#uD#`TZ-WUpc?-n|fDVP{OA29v8hK0yX%?uPWcZMzNxgq z&H$SV`(1K`A%Wqc)pSF=ZqfTCW4QdmF z1fCJaYi+1Ag3x4gIwp4V2cYO8Xr(N|enBwApx-(x@NZF@@f42JKVn@J$LakJO<)sq zmI`uAXjCsksH#7B=m=VudU!$4=4wgPN8NUNVi5d8(n~guET2+LjWYO$)jNICukNTU z$6WIiYIH!q)mZ(z%%l&m4_G`YL~tWj#u?~6&WqEleD6{Axz;M5w59gnO9JZY5&}vo zMX)O*+tlYomHu!(@xy-@dvdOeA)pBEbul`VGHE=%rrNEsZ;vQ+ww9V~Bf<7KLxh^u zrtpW}v?>=IoCB}Ua{1ieN(!wdpVCihi5LyyyWGXIOz*-(NMxB|58KU12cPe_Jm#0vls=csh#dD*yM~6St?T1MR*}e3zf=1 zw|TV7rX*3V<7S=G(7?JJ%|fy5hc^_9DjsunKQdB5fK<+7paGr|qZY42Ddj@y5Sf44 z+Wq!RbPcQ+QR*p+>Ik#Q(@U=mS5YVCb1C>NqLp~_o4)BJQF{5=j z&^zK_mgT^7p8tGzFX>|fMVKyu&$PYnmseaEgc&w;UW*kP0b<)x#jCZSx+6E51zs73 z*>NKRk>H1|g3l4SoP zphhz5JBb&v_Qt`AaBZ1+SY_Mv>$#E?ZwBi-NuS8|F)@2SNk`FRZp~9U&g=ECeB$^) z>NBh|^3IQ4Z(%;#P2v)LT2b=4;X3ke;UiQ`M#kYMdyfvwr)NxVHqbQRf^Z7U9~v(T zyqgVkhLtkwpnX(^yz(M$a`?WkBTcI->=rmY}&uI z*|k|pDglRwyL$gKn6v3@Yt1AL>Yz!w5Ef4l>dL+D`@p# zJf0k)9ZT0aQdqI`|8v)74%&U0_F67*0u+Ybg0?4|xl+@g)Sj`1TXFTvF&r~HyVk*8g62bfa4tB8Zx@R2eXP&L*4b>bA-FZbeX;cqKPtCmm z%5L-<>5wE;qs`7J>R12vbXk@7b+5U4krBv@=#^;iv6n_Vq~23#SUZkHi5AAKO2_@Q zJ4+w%uW`-sLQP?o6a5?EWPrhmWn`~<@nMY#pS!t7%K%lfp8g;}(YuwGL;lJU?$}zt zWEMvuZ$rt2HU)3@ckWGqO-n-ZP897J?Nz&7v(lCu;VcQx(Sa2MrJKnlwkc)E8o`m~ zEf@XkPB+Z0lofKj9*jShZo!s^_=}GmBwz|KSI?zP#e;a85fA6zTOpX6_C_7#U4><4 zpQinZk%efJ2r`Z|lT0i?rPd#z{!%r;8D7prpchYAok3$o$oIGdw@5g1Sm2?Cc!uG7 zD!mY^-kz%E8LiwKMgf z@(>AB*)`SRSx6HZbTa|c$ag!vKWpV9(PKYdDr6ks*#DUM7V_+qB4)>XS|8EDcXy8I z>W4$X@%~m*tF8&Y>}HYIP^KxCv!dtOj)$OwMR5ZTj>ylMCol z0e6P7nU^-bQ6gzlyvAC2k_v`-tk+@GzzHq4`MKyBr#u~wR-C+y;$uH{8sIJ~l!2?z zh|4YL*k>A0$Q~6yxs`SH&P{xyL8ngU$56HaICDzmeW_r*W&UEMu^uth!jDfE#&xNb zw`FV9U!odJzk2c3xID929;V!2Pca^-C!;L><*Gnm5*ukOS)aTGf!oEx82UG2-;tac zLgrLRUK_D_C>d+fDi6jJdpie5(1IZB0tZjf^zD>BTo{`zVDt(%S(?Haz8Ccd$rF9yxnV@n+L=8NYw#4emFA zQf`=Z&y?CQ9zwoxg4$FZYn+RruI*6^$w5B9MI?1Nca9T?%33By&wbC@+Mj6P{7f2zDv?vW?U z739Q{Iw}tDh)SxKk5W%1>0Z^YpTD4{fnYxooQ=?w0XqcIP{q0^o@eMBPMTVyln6Z} zN9W5tR;p`0ObWeeG;biCs)xP~tSWFz{3YpiUGYb>T4SB@u-6T|U|A~i*B}N}M*1l9 z7l0^ekgUWvy*ZFmQ4JAgpI3UGF#AOyvo!9d8rK*FcM*uEg$iHz`VI> zakg+D;NwJda&(sBL_SaALG7DTA*-mkWLutof9BLTMV(xO-wXMb(%bwJmuw0h^kaVz znL+Clo?d~b<2{!5qVOx?nE%7DYG`~nWndZqEBaU`=euaf!QAWU*P7T&gA|qv#@1NZ zTbZeG4K#du*i*9auJ@e)i>_jE#(NukF4hL+!}c+Ra3&{bi>5-<*Q`}>bAk()Z<|&@ zu~U0d(L__5f{1>dU0>`Yp=MZ#c3tLzMuB`NH@=dUdb^X+CWtGsd2-*YcbQ+wcZR$| zHKIVMmcYAtsNLj5H~&wq6>zH1X?+^7ws}c@i0yx~QV*lhtVvp~H8nlvRJEtGrufjj z=o`z)noYcU8|xDg;G}0i*kFCU{&z99b)9QWy8n+NViA=)l&%3}fcBYmzS`awzQ+he zTQdbGLKVO<4A*f)vdn0>fhiW&OshUFuW$pVC-ELp;oQausOB7ZLvWobZ|x{H2r%kb z7S$j5+1dqrw+SVj8|V5P*Fe49K<-ChI(a+WdrD54wY6_2i^LsZC&`|OcK>1SmZ=2M z>~2;44c(aPlJe0Mm*R5wLB}=Nr-SUCTaF{q^)pM58Sg6VqA;gF@7@Z7ttxfacF5l; z(wqLs?6)5;fXW?4EOd##G*@?}3HN*sf}dPo5l94nh|JtJ_m*M2L!)2Jui5~OlJ^2> zo0;!bdqNkzr)$0_#V>MX-uE&EyFJUn=3Ome5te2q zai6Sip@J`!ho33bA5-rz%R~XW6$?1RNk&ml4Rv?}$>b^;{36Mk$S!{bri&MI$4fHMwqsC+UbZ_D|1^!h4U>>or(-MA-E7zJ`DKwMJHQ}y~Vns?1 zCb>_}{d|H%lhq8c%uiSQlY2_wk&Ma{5HxBQWeK>EKtp{3;Ry7+L5~xasZ)L)FG&4^ z-06MCOHRJTveib|eHSEWh^y=$=PwY{skvQdFKvPV9{r=SO|v%7@t-1())II)bhALT za4?-NItb0-7JGF4Z|@L|JL0pQ)J5sMSMKY&9U z!N%e^OPMI)kx81Q%sJ>~89wTME(CcdBDuSiSDuO}5up9ByKz#Tz{FvRfnzT6KmSs; zx#m9F!|}~K*s4o)`kSW-HGe(&DiuHn)nA`u2SBfmKFyd?AH)nmMt00=>X`TFgkbH` zW{ShuWOa((slE%?M*eY#aICG*S2f=4Yk!_6qW1eedz+aeQY=~UwFeJSDKBbY4P!(jR%Fe z7e$c?m*x2tFF~zZtL@{4P1U~4=pu-Qsu<3NMo_R+xBT{jKRT!zuI}t=Cs~RaD0~ZA zhE=#2z<&J&Y!j8Ffw1G!XCqUc{9BwG{F;PdvSM|jEsXew48x%FJh{X0KVe}_wVB|s zEbdB+IB9lFkBN-<4L~#97yK#U;J^fD#e}cTt;~5$S)3po>8lNMtg841l4gDRe+ZlT zUn=of*yOz{b^lY*$Jz($xXNHxTw)KR=XKtyygHrHgS|K!#F#@zONw6@#Z*n^D0ym% z48G-09CVNAWtWjfKlMx}#yK%BiUFtY+`d1eJW*JY4Rk9Q> z$zCCN*vu~LBR;_IrnP~;E-7=B-;(2F66j;98nv^%%>8{t^9V_uWq>eo-x?3$V570} z9P<%gm=`i5QxhznNlqFxKxHvgDGG1)eIBhEKp68VwdkE$H}y6P%4zl*n>r=GBMlQ- zVxvhFyj+>NimB8D2>p)o@Jq<6c1LLo8ee;CAh%b3VpCjMF zl2%pDi@(FqzpA@MWLRmWE>hub%)V|+&7qo#4&DvWel4B zG&(oB(e|^yJDIBK+fo3wFAF()vZZ+denrd@SC!)hdD;=Aaq9L(7mOEw06^R2D&6Z7 z2lr5tF#XIlZ;0)~VXGO^)I2fGec{-m}76TMafv$0|U^t$?3Ix5L0Nn|_vSlbPXB`dC= zUnDQ#aV>sfh1{UyKO+w#^|$I4POvXFXnfe9jOZ%la+D)X*p4|PCig{Mtp6V)7BpkJ zK%}yu{e0%wI>`y1Lo~%$fO<~ydS`N?m4p?oyv3Uj5x-9u5fD*tXE$s1C3_oLeLnlF zb%8E3DZ?3GaV`3txOL^z2bDsl>0RjZ75zF&RxvG|8Ui#-<0lzL^kcd4gEH<;uFLJL zJOzz!o+e1xNyZF&8$T}t&EugLl7rF)8XDey!k15t`@tyOKmm}8&5(0Uvl+c_H#dK< zB}~TIEdwR`P{LWQkxFG^%=z(K69Iqzpy80ZBTU&g*5w^dBZGaIrY)D(X8|X>GRrV$ zRv!Q^X6<+}s_>25pn6@NZ8AcMyQh#bf&5BpjFld!$wp327x%4Up*-KGaUdaYwxwv#Ok3W@uA{w_EQ5~$}v3y|OTbx!;7uc>y1UM% zl_2C7|0~HJGsWfjmEi5nQ_4?|>kKTE)4D2ksuDd7P41S$kaG!qqOlsoqpM=KiY|k1 z$D|ETZhzRK*&3t=XmY0WPI9Jg?-n1THeJ}Le;*jwAxV{;&UawH+TZ2=!hcuqtyzL~ zH>20giC7@DNsKd-w%5MHWXVN*$P%Xa$deX=NdoeWST*4aKHXT@61Z{ zYyM-DBhB1O)mE=*K@9se1KyAE3pj$cfy`hq-S_-P#gznqEhAvNKK9c9Qt2f$C6ud> z;YHt~=bLhGD&;|7b%y>@WnTR)TYu<1Xp*N}J2ro4<4vz0&Q0)$BGyt^FdAZ$=OWNba&z3E`J0!GVEP{l=Udx z663GjUf=6I=5x5n+m(JOM6spd#xZd#+rj(~NwN&?cCZlYX1!bsxMN-puqIg3g%kt6 zXqNn+l`Zmv2DFeh?~yRNHSh3Ele*w}PWcwQr#Lid)iK~l=~+XKW3M^aSz!8Y0Li!H zVbjHtqa%|Zv6}M!y%7tFF>=yWvo6IlFEIKzrp_XM&I0gldTfr{Hve# zew?x}-4GHm6W3uIo&KYv$%#H%LG*#A`76YkB?tl|;AU`(X~kAH^jG~4r}f4_U<2g| zx_yUJ;liS>I$Qh687Z_e_Cja`*-ywLZ1C-K<_l#=&|n0e<#|~ETVI73tgtQ&5iOy(ry5$3^Ozxt&;X(PVi=C5Nx!d%?mvASoIsEX(j`E;qJ%7I$S1mxas zY^azcdGck0uBKYzB-=c6k?TB%wRQ$Spc{VB*l6Dd$0Q6vo@^Jt_R0aQa{?b zkI96VLF#+yJvDQgDtKK<{f_X{jZx*r^z+N3m@xY-h;A=YN$TQtJSdiCu%&7ze3sX< z0af+_1~bB9DBNhS2I___)&@zC$$#6BeOe``lgesQ^d=bpD!kMPM-XjDWkPZf0{JF$ zE{nhSDLqR>DNh*VshD1wb#KDonZ*N}o)Js~m$GxPd}jsJo6X|kkA5{tl_6pyd^6Ss zCF*5eTI5XZ6}G+U5rIcV^RMOX+(2B}Z#sNCV$Muj@^d}(Q)zoFb5*;*-ifW&EqDrl z6qg81@ZT;6wY}WGCb2h5KCqnVv$ad5g9bNZ^A1-3)_~@-sTvEoRH(+^Vj70(FPu}3-NUg^wZxNDmoH|4*6z3w9vDjA$Mi^!louA zv?dBc3SCruFZerHx0fwwZuX_0puvR&$WY}nwQ6LNiEd(f68Y?{s{AdhYIF|avxpAr zpGUWk`#&mFM4o~b;mo65GYe#4Gml&!7U}q$cfxfRJAFr~FatAo{K90+)Y<3f8Ov;T zRthIi%MEW%>go#xTp%ROsdZD znZZw@cu9@hfrC6qRsxbLwm1#FzkQIrpAkUU9yyqdT4Oe^xyXMQofWp5KNh27Q~twX zUZ~p_zVYi86(P-K*L5KgL(DC@c|BrOY|c{R?Z=9vivGS>jX07@Hqo!Z!v9T!#j$r;+$pSu1J!<31I#XL@&TSddvkKF(HUewFH39>yyl4R#M&Wl!E!j~BSW_MGa%$eyH z(Uu4WE_b8J2JDLQPuvgbd(N`N*lR50lqZw+0|ULr1ii4t8@>!>P|B>grmP%)%Dg&P zL5SOnH@&Mqr40u15U~iJb%q)bzbLJhHCTx9t?Z;T8{l-=aGha}0-DgP!h~+fgMu<* zNIYBHzc)3v6ZJtbc_f>5v`?O{{KcCDz%EJic7(Ky%v}b=ZQsUXi^R99lN2nO9OH*| zUF()YWih>d+X%FG-J3qzU!=M9m*r0f>%^G|G-GQJ8*Q3V(a_6Cl>CRm*So4wKelOg z&&n`yc6yi z!R9D201$rnjn-#~<1^W)6RLAaVt$_HRZ3|M3={`5<_B21&0!R9R&Zct9Xa}m8KR=1;+H%`X$h%t}(_7{~*9*(^ zl*w(<>e3;^e`+Mz{qe(}Qzc+*VCOdV$rK!Lp(wn+FdjiWc9LV1AL{Hj@;fgtTHAma7#S~QtS9D`Nf18cp~U&p6Nvg6QR&rC09UVX@YFVu>cxVT>n zj{)Iho#)~)SfJ~)RdY_7J1n+cnr0uRO&{m$Mk{I|Q+03EfQbQ9kqrMR?cdduDWZuK z=d|qGamCQdd8uo{oUC9zn1qM-z2)*%Y}Z zNv4D6rBre3Id<9u`{jpbzAfF}?9Kcb<@=YD%x5IC;|ojjmKV*rNQT*u_L~_HGYZCe zR-~!bw5d>gdQZ|u!2l<>K)COZaL;-cNC?*KtfU)e1z;moL7h@jgBuy`5_y*=Il2Ri z@=3OJ)htX7+LY=RomM=U#;?c;M zj#ZZci(rdaDg*cQi0St~t!t;!tUp1Y?eP-_$G!b)*FzVZ`D)jTGG>2_%BnD2$F@G` zuWCnlT)>iY+!Fvc~%dOp4L{iOJ!kF$hfp-Y}SF&$Z*+s5X~!1R!)?#0!fi< zMfqI5NaMh1G-wF(pO?9RImV-Sz~9*hB)6-^scAH;xpIPE)tMA8+Hw2Q&mS zp7g&HBlLwosn)l=U_HZT5$zuX8QpU;FyVN!aqpx%r<8GB>!%70>U}EY8LFxyxwu)% z{zLhV{PMcYwFaSM_xCuVCSspm6iNCso1m7OJ68n=_SQ?Bx{ov;*zF<50gj2wIE$>+u+9?=)JxsH}pZ6@i7FtkNtP|N3CMD6=G;RuYEKRNh5~>>tMv?R1{Q z7j$cDF9I~}V+AjF(;uM3p-g|1U8Uu%s&wMJWFr9LRR0%gXZ_S>*tTgXZ7H-sOL3Rr z?heIC@Lxd5yF;3 zS&hb|XWDa+HYrzHspL22>|Rz~(>YGLW0A!TFTi!r2vvU~-?;g5 z6^k#ssncCPAC6;{&I6~~k+S)!S`17!KG&CPmpslHBsP=ozvpqfFF!}iW-GjU6ok#U z&odxa^sAm6W1;Pj&6P}p{h`@WA)WC=J z&BYdd9619V?TVp{G6w9Av)<}b{JWd`Dh7^D$k{OTUF(!FF$bK=t1{s4>?%S$!3qNE zBK3eg3eqFet1c5$uAt2&v9oCM|1itR9fdz%N2IKWGm5d%fANE+zoGf?d-0cKi4ogPiF#Uo~{$jMkVZ z?zyw=U32uVVb*_gAOB%^bY0yA=Ez(N7ehOno{TduKFG%t!}~b$fQMPRes`6GK!Km* z)Wv#T2S7<4XS^I7=iL$>XEsg2LtmxGw&R562goE+GXzaUJa#wW{^8uHp0ZMuG=2nY z-j@aQYbKa~IYoFDFE*eHpEJ!j@}g{B;vW~JcQIAe23EkcIp0|=T}Db8J%&wanSCF# z_!)4j$)i|AHx*i!bES#IZCdyTN*ou+3wxPkTr(+hayI{Agp^2YdG{Nt&yYg*wW005 z(vRUX?W`K4vETH(8Vl`?NmZZ^Zzh{PI1MBHZr-Y1 ztF1_l3Ae?l=|)YRd<_*!{)Fc5qHCgKGUjHH;`$GQLw}2yzfV_W_eh{LIn#YLqf> z!gAxw>+Pk}lP1SVuE`|v#hN!?<=(MKTYeRYLG5?w3$Bi-3<#wB2|2qs?^U-HxB76& z`|+}z2?YrW-J~N5@(;pa7@UPWOxO(o>s-e&XHNH-g%HPsOm&xibe+640liF8mz}p& z0Y4j2nS+^8Rw)FO#l}a+yz8onK{7d9_ms=SsRyCl5z+FTdBr! z%K@#SPoDtpX5){9Lc(7LVg!#ZYwS;5f^Yhbz^dM! zzxuYhwUxSO<9Jl|-`CJ%lu(1T;KWZbzONm2xPKTfVP4p~YhD#)t^V>4LtSaRQ_}d8 z!;`bi^mBuewW({wh3dr4nY%)8c$TpDrPoLLcuL4bvRKRnQuA{&TDD9+{noZ@^Ai}w zRM%_TguhuvN`Z!DTQG2dC~rePvj{YciJ|}Hi%B+L=GrQ3BsKRITJC*XtG5s%(LT%P z?PfO)wnU07oztu~ZrcQGqrCl^--b9&yqWU*1e)PX_5)==@XB_`aTd_c6_ryc?eD7g zbkWTKe6N^cdzCSJ;Bj}G=FF>3-NzY{pW(zo6z_0$#9n-~GO0haeA)c_CrRAWi&Filo ztbIX@N7-qyH$3JzC4+%Cj^6tEX_8n-XiQR|^0wJDh3==fQs=Ov6grIQpmno8#ym#a zQ?sfU6}_U7k4#>r}RkQine^r&#r(#enZDKt06MG}i**4R4u@KnsrHUz%c+ zmU3%KtQkPh#bk$ep8mr~em|a9^=isq2!End|K|M~7nd=2T|v!x!kZ@D6mzg|fC75x zL9>Z{YN&j29A1du*!Fszs_3SyxIx(}G6dfCDlCZ*E>5@s;sp`!X+pZPjR@T{>JVVw zCOd)wKXFw@j`;W@;(r*gC0M)&EQ)nHkDLC-ElB-Monl_oxs97!XC0LLh+PKz36LU zP6Mz%$)Cr3aw@m3d@Cg6`|b;Tws#&CpL0PATfpo;!%q#*2EjTf~IjRy9WyjjS*r8EDitEQ4Iw=p30?gAV8 zk)sOw+?*q>CF~G#$=uH&vuVYPiwxR-RVxOUgiBHXE^5>)9YKRw$1WHM9K5$yJT|oPGyKTT9 z_BrQ>f(vv!!iGUKJ_QG*ov;nU7k_)x{}vG?&1WTdT0k}a2H6v(Z@e5Nu;%s~0r-oI zFijgl8y;SrVmhe)DD|N4ivcBwXcv<;Tqx9~Tq$&(e`(~=`BAdc&aXJ2HuNl$mW^AtW(Ha7Y~8s-}}=huDF zA)xNhfwEcdZ;;%w?ljYW@reg5l%aIreHfK<-m{B+G3?bt0W>`PHrwEGp&tz-gzXFi zhy7-La=PGJ%nfhk#12%+^Scp7zIe%v;g?ZZ=hSXAISiY>e1_j#!L#*^_*yw0x%niS3&6Qsd%zCU z7ia5p;7s3+gw0Th;r3>=f9IgIT@oUhY=}G>7>c`qB?T3=zOMA3%VPD{OKdC<7nZ?p zj=@q}+34+%HEFZF$lwY4&4g(TB@}4t@VFz(QCT({=`k@I`w?77e}FH1K&9vw(uK+M zE+h4&YVCZ>>g&pPCx#@^YX&#m5O$&{Ti_aUsk%{m# z@)gv>9uDaNa2BhFoFx|%ZgZnZNe5##BdeEJz*)VTrPJGQc-0c^Ds%uW2%y?RpcJivgh&Y1jDFXM&pxx4MQxJ;y?WUubd@3EAvrHk_(&QR7TTP!Q_j% z=gQ-vk!*6H`9Qi51Pg%bv`J$v+nSYmB1ad&&to^O(rh$+ILg$*rfpZocuuA7OE*;n z)-F-Ge|*mMs+Mp5@kFZD>3U6KquzjvnQH`?;sR1=IiJYUUqZbwK!`S^vw``69z9OK z=s14r2Y?n1sJAZ4+-c8Xaq9*;!IKTQYbrvf#JMIFnLu-P*n${dPM-Iu9&>}3OWm!x zGfrLkSQZ0E1qjVtyJYoTLzs$jk?PFQsNL1%OHn4pdWKvAvNA-hvrG;7{Ls;o*7&6^k7!LNc)U#IA|-J*!4og&BF^&|e*V1gm9w(B!wL&aXKXUL zbWY6ZpyPJzT>ja)-SZ&@m2aY#U%|W*A848v5eY2R8C$RrNLH@HB;l{BcP(vc?o*qe zDu8q>SkFwlWbfuO*-ZAy+%zuU|%fcNzHwhy^FCG1P3$2z&PuOpK;w8$!HP<+rvQ3t6Q*uLHm)-i})z?AhRj zQr#7%9XHOPzzfg|rbcvCURcJV7d5m26PKj&k@y^yXd&jED7?ldJ7?rs&JXrx#U>ZK zDfJ>MzVd7yXI#HAHM`PoP>Q5ca1CFx+=0nrB|N1uxexNV)8`#0caIYJoA689ojw)M zlA9|1CiCOZDUCrBFYzFP1clwe$9XBV1sBvy3eMeXzXah7U}xi%P`8_O8rHz`!&-up zJ2k$nU6o!i=T%?W264L=@-S?oXXH}I;RF{b5VoPo<|Y4GyGwTNVGULoQ$4bG63528 zrid(RM_c|BVOgXFp+%T=@$S#1o681ifQ|bp84mU`cA+KO@THKny4RK=jTd`tlp&|z zephuxgH#{VB%_wiZ}=}bwFPH0t(&s?P-AcngnS`&K<6J00+=DcBm5sm;^#NLG3G94 zm7$X9?hSm@rQ-)0v;pJS%zI?J|6Q$0BmD-xRzEV5nw6Dn7G*BOKlQp;^&74))i3$a zx;LwBbeSn}(%{kytLKNFI?(oH$r4!r9cyB3bzTS&15E6#OFbTW@$}@fS3tfLp?K*` z?%8|P;I0F`jup1v;cWTKXK#s9sm%W<`c0$GBU4X3KavzQ68g_&t+a_x76p_7v~V%_ zIzLbU|MwXGk0(6SCQBRsl8uQTo5Rg4Z^~Eqh@C|YeQb^0twM*4A@HKIUKrtXj51K` zGtu!BeVA}J!h)M~OuND9_)Q?Ik>m=;-lN*|Co_Ex5yWQS26qwxy9T$`&zH{0AK*aj zq~pUxvk+K6x3-bBWI(LjCig@^S0@JlKRX zrrub{kJVU&$rbKFZ<`z_Fd_dls$6$3k;iiye?{agX|L$SkJ1u`YKW zx@BqaK^p4YyuL5#LzClYthOKXPnXc4{0uJw#o5`>%DLXa;nQBq*osz79kp&ZwOSH! zqKy>yT)vBS7F-rUTyJb~OIP{(3r??vFR`0Lv%(MlDW8TTy{tpn#rO+9MbNv@{=;C& zNt14tN%nS!T!h!NBlv$fm|3v#aUP=?3i2^rV&56Ds6`OXE5;l)jOvCPYkxlyg2PT6 zR;sCf0erBKO1u9sh=!V_%_1XtvwNebM`eg33`${;T2PiZt1rD<3I_YIN2|}_;b_g+ zZDmbIx%F)wZ6N-_B95Bwt;U^h<5!Q^CC}qK{pcgDG39CVjnf76cm5M<2jwk-E7~6? zzd`y3iWI~VE$I*WOa7QV>l(l_LNp26V9S93l|&*x0ySKk~83Cuu z>~OY5;Y;OYI~Jj+S%Q)tE{cXl0X`!~;){W1+@a1K=WiHW_h zhO!C8%z(gxX#u2|s}(}}+-2?t0EA-xc(F^vHt<~c1)b-<$pv(6_F1B7UG~7WQ^(jV zw(zvZLK)VO3T}Z;U!UXY--kM2)jLKtM2VNNa77Ywp^36?oAtIl2X~nbJKb7KK?fmtoOKE4PPA>vu5W?XGoq zj^c+C%t7s+aU~zwEtrI^t%OX|kg(o~Wo>Qwyr86uqiUx)xx~6GwIBvjy6{K7k(l$S z3Wp&CF<_y{cs0x#V}wvERqH^PT6fp)>Jd%7+ErZOl1jM~;3`@So^mS1J;R+QeEvsdjpfdmo&At5TY;uqgS zE{At4`m92qRPIW|jRe>r@2r6xNgL5ZXAdcB41imRiDfBZptaW!Y;5KOY8q6F>)Ngu z(U|QDYM0`_7%#9GXy)$sp8BEk()Eoi8X*)f=bDWiGz*rLum6%WdV>< zPj+pZM@jaa%0SjLf?1)gaeUeXO4!vUKQ}oMjR1#&@`&tR_4mg{uNN1r4cJCKu;KiY zrGRZfZuQ0e?1a0=mUdC{YmVY156zk(`N)j>Ow}COq(UihV85r533Rc*zNA^JqBT9* zySY$ZwI%PxKMdg~uN$delK?U4?qPf}hho-M$rIKukDA(DH7<+Lzt;UjbQ)9>GG=9B z$tgaeG~Z1ftNdkS8B434O?Tr;HQ2~1S1v$mk;!hParmr^HStZOWM9(j*9GxJvQ#U) zFHYyAziuWDr2-0!M5pwB*!Z$;(dp9lS6Ht5N25lwl&b>%;%M$S;pN)sO7<=n7fOgp908cZ2I{9>hSSkM9>>vAo};! z(@_c6rsdI2y|T3oa6rVnon6s`7vmy}jbL>nE1kW1WWV)AF%g`PP5A}3)!Ti22;!dJ zDY-GJ#icXyG$A_EzqJH2PoF{h1juv(Ut6?BF>;mzr(jCoDC30;2zmck@wIq=W8`-j0uWT7R#zO+yz&2nvpP_ANpLX;QQ zlBuHc;_24$pR1}a5**p|(WB|A1JYGh1kYF~ORC?YcA+qe0M`YvB;=_NXhS{MJ~Ml| z{sCQl-ufd?FuFOMGSL+y6UWe0SiyPt5j&cy&&$pDvZm-tYrrk``ff)|v~&E z0>v)jI^R6>=>=4VWfL$+^XGWRzmwQ4EguA&cdZX=g(;eixBl5%9FSN;ZejBEfPCM^ zPllnHAhvKn2mM6bY*C#8`EDfnv?N<5rPfkfhfxhuVFxB@)A7zg3uF8A@n9nA=rXSg zBIuEw7!Dnq72w?SWo=x7dlUo3BwL2YWFkC8$M6F=$iZHBd?VK>9m&_bcrN$O0!?XW z&?Un`&Uj@xH|Up-g})}sdnSb(ocrBhU!^1yU1Csao$9(Guqh@1Z(3G8`heYLTeftw zM&&jHXV%ZM)3-~+f~=CAzO{(noN5(qL?EH{Bnxk|&))YKOQh=Qs-<<0Sg+Lep<${s z6ve1jia-cINGiE;o%Tj^$NBzMxsXO|39-J(awY04noC(Wj$Vvv zDIo^Ufq~B*b8kYvJS&P0@J_p9hRKeRDv9wGdzSPlPU=;tX*7INoc(Oc zC0XAZhRsWp)8(;mdJA_fI5V+S&W#cp2-!yJHc@hmCJRS=g%v#Cy7!X!(|W2FsaG#K zV=VYNXNJ@}{TvJD^Ze|~U&{2XS1ijJ>&-35Hs1bpR71>m5%)d!wzIbtC6%{x zb(;yd{xr6ASwr=2=gL=X@*ntOR~+2HF7n(P*$GS3Urnl^#*BGoX?bi5QJS0BXhZY5 zCxYMV7pcfmFAcdhEK1lrGw3EO+QUBV4rTw|3;P+{9udKznHlggM%a(H|C~7iFH`DJ z52m9|fG-$d1+F~Kx_omtGYQUcX;7Hbn!ukn_)6D}ruu5ws?3`_NC5JS?HThS?!p%&M zWMtLI%32s@7^UEZRj>&;Pa^e<(6C8mM)eXgu>;5XL7FMavd=2vr16XPa_0K7Y);*n|GQt*1t5%YH=-t{?lIAuPBS8&~e(s3_iT zN#d&7m`1}*Co)raKOvQZZyH>iedcD$bz#KbpjNs3uDMu2P{Ws?+gciz(yK;mo{@Yo zz<;NGIql=d?Tu5>sV%|>&P_r-3IaXJ?{r^~9jdJ9v>Mf>hBf49PZ*9jdWj0#_}vu^ zzJHqK7u65!KN4N2caDMt@V}A6itRkp0c*#t0&Jgto5C4esWmdwS;P#L`ki4R_pg4UI%_I5#8=5A1H0NnyTmOCp%+)_st8*q*H);=gZSj z8`drJ6-xMG+1Z=1*fAF?$!cR{tc`84nly$cI&fI1CEX!?=wsOq(2Ko$L6mYgO>cX^ zhvXot!kC^S)1MM*PNSCZq4XyycJ{M5 zTe+FM*IhrW-K>*cfg^FmXgUbAXB)!2;R6oohRXU8vpL3#1=?tjxUqk!%M+d9t! zhle$Yi@~7I9~;N1?pLD^Y7R{hSYE+zR(@)OFx5U`FcHp)Fr!$Ni0H6nVxfcmL|CMs zA4gqrBXyd3a>{H-JWuJdzwCyZ84xOgJ^vfR}S3oRST_`bQKT!gd@u7&;BFhz7j0 zTYScV5Zh_it<&2IkytUtE9;~Te}2-k(*p#pcXP5_e9BfyFO-Ug^Fw{?$6WcZQV(eoQSG)^-Gdx{Q?E`0K*)E zWB@ccHoW=<&lKVom@w547-iD@h?3Q^z~EBZnMe0h&W+p(I+Fik*vPwuw)d62$-$u` zF2sPnU<16Jb6czc{0UWDDKTHEB(dfEIpVft+{sbFHk{)9UF^8&(BvY-xL%PtnLN~i z+^A~%$z(+)q_rU*$Is|d*qDP+O8iy!n1o)EXhi|{m2)5|w+MmYWeqp-n|tOa97#(2 z6AZVyWIb)wP}-eBIwmr0`Pod|Cz}6}^NGNVIOo>RV_zCJ3qpd$f@Cq-wrPTwK3@k9 z4mK|M*V6~i2$yir{=+zD&T*b!uuV>t!%bwt=>~WK$u!nJhv>=?Iv$|h4eAMeV&H<- ztE_jV3pS356N0(RFyNq;5+;_DWfQ`o1?6p^()bT!V&UhN`t0eeda->+{`@5I_?Nze z>^@>xUo?kv(N;SPWd&ukH5Y@I)QuHY$?lSwo?7`_uw;*TA9f5#4dwN`ONZl&ei6+& zz|xhCpfWAz8TX>aNNCxcW88O&D5ie#61~5Hzg6~Lkk3=O=;mOnv()L%RxXLyh(Zvb zGF=)MT;P80M?_^QpDtiz_MaBm=;bldu1yJBy4c`^fcQ`pgd)&tUtssmtyF>NM(L0^p5dSDK_U?RzAA+FN_56`hxbL!@HxM6_RC1;b#s`YD8s4uU^ zf`R4fVlnTCV9^a_)Wpl=9w}w7_LpJM=?NZa-_9MweLGVpSfe*HU&4#AlpM=%#yUt3 zCa8x7=Oici|HHVg)!(Ty3RhT~q3!QWKdK`r4C-fL5qnZvRevyeL z^>Jte0e=~=7fWC_{bUVErSVl^$W{)e?e*A(Ov}dQLizOdlt~j-x(|g;v6)x-G*_x|6#aW18y8BSCcK; z%CoG0_W58KWtwleFuLrTY7gy=Aq^K#2<+MlnBfuiwYM*W)9D^OyDJ*%%3En07bdbq zHsq;ft&^CF2Ac)tbWsujn$0DLTg{m+%}>mAJd1&}p<4m9pZ;VD<3)-T!v~^;B5|!1 znTlS6G_XzYcZGHb1u2TnK3S7GP9Wg+HxM6#Vj21Y0Ep?iKz5WS>ke6kVlzhvxnS|6 z_1~{^z2S4@vjgyY{1r|@1Lw$f=npOyE1RqIVz;Dp ztJZT%&nJ~z>u_ z=2w?hg7z^MXTM9MAa#pszIdgycUJ9KSqs!2-`3`uI_zL>%@303?vE=(s9uWa>u;6C zu?eRpWp`t6LD41BJ)|Y^2f^puTyqn-fzn;qRMI;Jzg=~WDWmKi++^xKdMA=ew@~Qr zm%K`N3>UegXgQ40NEs~JQq}7_ITiXt7`pxthj8Bsj$5D{-bhqiBmpFF^#ire_>)Rf z&uu#uJq93!PTWgLkvy@N4n~DVY&ntC2g_O60+Z176lhlQ&o)O~X@kj}fKXeSf~rl> zmhhh8TeGehJ;l6Z; z)||(5Dq5tM1+GRup&PkP++aHX?Tl;1->s_v7gc6mV5D|S%r!kg2Qvx`ZZG^b5qHtN2fo6^*%oV+5@}RiAE0QK-6G*JkES>3yJv>%ftDA{YM#{28uG=7;=8 zla;oczsaN8=NIlN3oB&z3by7B62t>|{j>UI25fb(f*NS!2+S>UI_UY|P3l8s7{3Nk zH^%39Z=igeN5j4;moB;?J9As24(fBIjq&%xTrN2}#$DvqFZ41nb3okD2CP<5(6 zu#tWcABbK>%e2p2lyJlW6Jx4W=i^&M{HL+045HcJ8^^VtpysUzENZHNf(3K%i9Ns_ zbDI_ZHY8cXuwm*q!5s@hmaxDtfcIcmb%!Tgzhwi`l2rtj$)D1eKKWaWPmifF?-@M@ z7|A*hz0X-Q+CkB#uobz4w!7P-V~#G75CWyByi#sac;Xt>Jl1~Q7xs-2TKA(Xx&y&h zKEIk;uA6i>R^CNfBUlz@*V!L&9pa+JqY=(Tdq1J02S4iOD*1}X+VNs&(K)AgNoUsibO@v8a|f$APx`-}h(S*0_mgmp!F9t2uViUMGZojko?bwR z`R%?ZJvSXI(|d{6#B0^sN%0!!iFL{(Q#pfI*?)EvSW}K%rEm13ORR+K7E&Ni6+s{J z)sQ`fc_KgN2c`e0`%5#M(TvlgdTsR|CC5VhaGdNNp+$r72P$9h$M~z@oz8tXzaMa~ z9vhaW?RZZAVJwXN+S=p^`?8NdB`|HES+{bZ5-qbKjmlph14}0LsG515wa;+VrCJhO zfa7{^eg^TLKXyd{M{c?vXtK^PjE<=^t`zxGKdM{LvJ4nydf^v^KEYXdck%*_u2k%( zij`R(s7S8^OMbr*@=T5vAgSmpVXTMv&X5(s7WIK=)55Kg4s9 z9Ke44A%*xu{o@p0h;metN)l}9q+;~P!e1)S{e)bALFLNo>&Sy z#vYpahqw;XII$&DhTnJe9n zq0moWs2jV;kfl!BJfhuRIxpa!?D8fSSw%$@u#Wc3Xei;$ZA^4DJ3&6BJ6^;Qp6QoY z)xQ}ReGFDS^{%6nGgNB<$ZD1_Z>{lPXmo3{1Vwv3`5?5vvB4=CGNtLbqRIb@s_|nw zQ!2GL;lyxIO;-E@8iYWI|Al=w$vR4Ck-J406cig!DS5wK@8p@9DDO&!w5?UxWS>6KO{|ep8IZu;Hl$UGWfpkvikv8N@jf66iv$2gyM-3>sO*VuX0z2#~q7GL2?Fo%m_lr%}Eey<$^~yLXhv?+pNe}Zk8qex2W$0DC<Pt z*E1l}{c{CsRXirwCne#Y=_PsUiXBDBOKGwffmqTyF&FM`(?{a7w74Pm(jym;6>@94 zK`)`1wvJA$nEBywp@yPR%f~W}KQ~Lo9OSBTGaV_L{)#W>@c$}Zitjo#fowHI6MjX$ z#087niXP#=d+X<0JQ=;xG!np)&pqY3>YiSvh3QS=UIPd3wOUcYlR+T_5 zboB;}gy!qboJGVKz| zk0W12%DelxX|}TNUjAG5WJ+|iyZ}HWmTh1Mfu>Q>E>ZK15g%lMXEsY^mcr81l-~5H#+g*1 zAw-#{7rbB$+SUi-Z&qvhC8DvoT3K(=JT!Hw%tVcjVxf{(xtW!MG5doVb}!CdHz*BJ z3;38h?*czBNEmP?)o$GbDcO^}qq)%Xc{?9v@HF1Re!QsJef9#10h8oAfPf6Z^#PV`aT+F8Q9Tp56Dg zPV(wjKXKZyOV{0oMN^%>{9T{)n!i(HYZm**yPAO#i{%HEel{LHoc2~_PBr1v4m}K@P#AMtnciPZr4GEI zu3c>{%pm)la8wwavOwv8s=j(<@5b0hsl6B=#JHXLNpxOzOoKQ`<_!z=fQF)JyCK_E z4>&ejn&ezZXJ7aP0&Gx8hk#W>U)4Sg5R}UvNOy?;fg}>K=-wz;O&EkOtJc{2Z-tfY zD=wR6gtG9z4TUSjJY;Qo{Vq1~fHiW57-<$j%1 zRk^!v_x!^Mis7i>oe~X}?(2KdF@ouhO|gBZ3Y*oG;o)T@AG@VohhB~0F~zuRl!aV< z$?w`&mWK?PwpIjq(yYCclFFUC~D7(!cjhRp(opIRmok7sb5j3}lp75$$74C$yQS&gVu zUE{pzW3{4!I{E3>#wNAZQS#SpRqGgOZT91)jpW!8$!UgvyNwI@SO?p<(zNo>MsDfm zH-y}BEVH`Y&zv_b;8F9PVV_NSZ8{fq9S~`JT(g=wuce=<7;7@YPNpNUs!TkNy&U2pV@>jsg#B(}_^dJ(7+Og|AWzfrIf9$50FZRPbH_xg>HH_D2 zHP(B?a*U3q16?)Zbnr#6e`Ft!m(3attg(G9l?{s< zZB5)Z8sm)@Sn|ldDl=q?#&Y{R@P&xq1{go1G*{~q*Jj@yq69l-18Tgq>lPcs$LANg zx~^I_vvLes5f>A<1uqvg$UBQGZ5%B@M>cm<)ex$_lkHD158V9|mX1wPosuczB<~j! z)n-Ky#IE(CqbE8{DLH)+nonMUm2f>`Hys+L${({XO}zH94V_Un`vQKg%_(zq&llvs zZqLweeBXPHjt?-j(1>`w!6}DHFE;*^mVh(^e1;Ztsil&`0U%CNOOLR)H{GFBpBo8` zShs-*(V_Vc?V?L|?AW53jgY6gN(6;Z`t$};!jf`ae~B6?mmnadps4eX%+ydSmC$ZI zRNFFrmE4XnqhJUXl`TuPM&#Nb2gXE5VHcs6zQt*Par>c^o@?7JDipK#A;mXHj!<~{ zH*=X};+2<@wq2-0jLP=O&g-cW1(GF9b#J2!_sZXU!Z%e+*voB#u?o>j0C-D6UkcHd z4gV!)c5w8-!ox-xD~iRm?s3z9ZmlW-5X!x99wxL zgRt=xRzKbRAh6g{x2vU|O~cJ1#&Kig?C3mBUZK+`c|fAdBh=b7gfk}YAIK5JleJz|#uVRzj08yxIJ~kOb^uljSIs3t%J|o3=FD(rV7c}=H32>#^;j;l8 zOh6^K703%;WlLE@iwp8++=IYHTPFqCU7Ry~o4(9T*6!Au6p@k9Y!xP6r0-sOaCmY$ z=gR(hm~-CQr_$U*%Pq_FJkFK**tCZuPh-CtOnkcS6kR&HERlAK@JO!2T5UB=mTb?_ zbGCccD=gp?#H=P6tu+FnL0etfxQEBjA|6rC<>7{-ZdR$xkQe8QxI;g0mMrWIIY1z# zcQXB2D_H*rsS)!EP|EsMMFmCYN%UXXnE%T<05`pc`;%GZWGHc7UT6v9^D@>l@0Whf z|Fv_$n#?dVM(f$+>M*4axJ=(_R9=GrCw!h(w~>cxnEm^A)Yvo33-t8{y^VPl6Dwz& zHEDtlM`q9Lo08e~r)|d|C|%?oO1P%dy(JFhq0J;qrJ{7f@rr>wG3i46R{_5hBCG3U z)J65GjW(5HV=B0SkPd%KxzAq3Q*A|7OaX=GOlW4Ev%qS5H3!!D?%-ow;mo;5CsT4~{`Qu?!_T_j za{DH-8!V<(OuSKUSQ-)tmM>UDclM({a;S@L|w%8KYjoW)AM;^ke&c zYolY5!zs7fFs4iTtv78NEOS$0OZ$emceT@QQQ#I9R$`7` zSA4LPWBR}ZYh%{doQbo*iRb}itnM?akl3!Z#hUP$dR2vg7(hE5iYWF`jV)Znn}KiMUs74M_V%W-_e?gN#{0RLg4mTz2_q8_hzadMI<3Rb&5u&&Ybh=O2;63(fLwb1xWHo~r#F_jE-|j> z-HBA(H9`WIw4a{&ywJo4z=S9C<3fxm{7t-)zaAhdnQu-JsG81nh5T5QqReYQoux-* zsgK4UyA*jnj!`>!+c@dsg$0bcV)B z(k$W6kl#rj-vU{B#+Fv^?t_ znZBe(T@&N1cBgl`Y5c?Rnz$L2VcUA~T3F6VlRb;9$9L%PTg~H`#&vKnv525u@nWH+ zYcC;A_p#EA>6l8)VMb(m7@4koyJCMnu>%J zQ#L=ed~b7*kjQxpRkdeTyXh8vugOP_C6nWk(5@6vFx`;mR#ITlV@BFE@R@PE!_2B1 zPZ(ysxJ|^QtupWn%Y~qZ&T>C%irYL2NBPeXR1CC$yV`Ktpm-5$;bi&Ew8Ug{h3c)cePyq zs@JKB#q`_A!MbRvjvG9_{qUh~s`5$^P!}|hjvZYo=JDIq-uDkar>q;x#k=bJkIy@R z{yokoz&g=xSM3tU9H8)pkdG1y8HqMa?`P^oqCZh=X%LnPj0$B%2>f7{h zn&hYvj%EbOdU+;KLQf{z+$c?ZEj7$|L_f_kpgWX~-!Q?L&SqdSSHmI|K}-v9-v%c3 z4{-LK)yvuEa2KknPNq^i{w{$Ws^3K?D&ptck-gOL*4O3bmBCs2$v^!5Sl#hw5V(Z! zAx84Kt)51`V$vj}HCa7{uvp)h8b|x`RaQc9F68EjBUzSOzKiX- zL0t|c9_G|PB$eOjoFv0ySo$MLkA--4PTq`eyz)Z%Iv+JMNibna(Eg$%kUdt8R4g~L zDl=MWZ*Y0-75?TgC4!Vo#3jzX&Dgqy#<~;y#qS-UBnd0)wa!=X2TT(&zFra^aw*E< zWeBmLS$6H{%#`ze$9}8H@)!3@(Pv210cqFzMRtvZ6E8cHn45Ok9v~CxvSqhI@Hv`N zsnMb7fReH{dWz{6w_wVch%7nzzze#+wnDw*0CS0AM_@UhzA0&Mj7Z7kXhz_`aWU73 zaU61_3=DpI8;0hAX?XlR)=#c ziGVEqbiz%d^vaK`pM+?E8t$Wfk%>IqVabkee-)81Lf_yIP>koY)GrQ1sxrnFxA)*Z z4K|Ggy$;uUiE4wjD<*C8mVk8ivdf{xNOlyae4aM7z*OyG?S-iDVzDav3S%3QCD?E_ zsLN;Z@!13cC?YqFJBabCI|14pEuEM30lI^rf(^9@%Y(Qha*6*EC*)ZVbVyY$e(d## zYUE!*8i+5;Y++%gIg6}8Iu4!8G?@lthlh#V=y}n*u;AjfCUbh__p!uyk>#<3n|Zsq z+SK?yEYv83neet7dr^gTadx{s7hbUo?`+Eix1iIi+93?;@w z{8KmOhu0u*L3DB^WyLP6zwR1hcRAw7)HGhs<=pui7(EI&E!#U7NJ_n zY_wcV%aEyBPORDLVD?rrH+aLnp%8^q-%SPdY<%wfNRagF6N@<80~E)G&a$JoMO zIcu6(i`h0Q_<5EnKYsOEPbBxZeR_QG-0ikPvLbE)mc36&yicM*_kO-{+2kYMKKm;+ zo|fT)8eS5d1CKvS*WpW)jS~<7HSFbrqricgC5j|p1=Rk8 z-H+RZ(^p+~zC$Os-;~}B2Yf$LE}1Qa1cu*mdO;4n(65wAuA3Ve(CNN0)NN4m(~^w3 z;=Q7h5Fw&%AZLZhH$MduSU1jb|}TZ4Q3 zI^T|2&MnMjcJ_c=J2fO^@nfQYxqkAUR0aP3S$E2_2vWz6ATqy4uP;e{|6bEeC=zj!vM zeaUgk2m2)CPQ>sYO5J{rA%UN{vMpn#@a_4PY5q+#^_eJ&>i$@Jcg?npAFA+I23nxLW>1=cewkk%@Ztj{>k)nKqv+E-pT70)b% zOj_xq-2p5Z^O7CwftZW7bO8qD;%$4I!Aam#nyPf}W!Yn7H9GQ6IeBFl`;CTJqvUc! z1=dU!g7$#4Z1&0sSTNwj213iLY71%tjQnHC4wrca9}=_QjfmV|jW^d#b(`^}=wuUI zsrd#4Chbo8n_mlCze~?XLG8E8O%7rdq1jl;#G|}W8b;>~+ zVk<}wgxt@aM#6Hnr3?@3j1%esA+ea)E=a2++c`7;fYfK7T}e}UBGrv4H~YH46NGLC zUbpju>SvZ|HACRS*Ew>ijMEw1nMB2&b^7Z_}V)ApM9oNLYHV?VX}Vw-M43a!wixptato9$2$3+X=sc- z->0QSf1|@RrXrPANXmxb*Aw3q$oFaL)-ltgJF%PCZ$ zm?DR>m5xO!d#c_;&VxQfKW}}*K12A#a4H+G#ij8$&(P>-wof>5F5!AtkB|WtYcsR& zdPz?^bFL&a)P16IY?Km{WEF9nEzW)2*k$mhOIBjaE`E;Zw~aUiXCz3gKIr_De1Ze#jX!R{YtmR z)B&Luu-mrme;Alzt3lQa{TiF%5N&Nn2_p|o`k$*xmCmZ#!idxcZ{2RYlPxu8jZVQk ztLsQ}&Dj=$)jqbHreMJ(=PBQnvCv8HKYaFB&if7r3g!uxjcg***x1jCn4%N2vVG58 zHw;Nr8yczs3|2~dJfvx*ALEU<2=g)Z?ro+|<29s5pCWcebeXAiM0kDKb%MU3nr;-1 zW(JLfPEXPC>am7L5B(^VPQ-?Mw_Gl=8~MC`75P>+IW+Ds@$gz?tJ*vjO(~XJ2UGfl zwYEGN`daWH*M&?ci<-%F*%FzHpzMp(OTyV=L1#|S=QC_);WppxPE}l8Kg)3nyuLW) z=mZ^X%r0sf`D&Ibk1l(fuxQkIDDHOd!kjDx9S7 z6!K&!ZbdDJu)4tWqcNTxFlSJkV6*=Xs)tIUNVUTmJ(#St1c|i&N zt@_vgPO|Q0iv5A=2$rAxsZ}w0!c{Xe2(7AO6}1$1-BW}!E!zo9F_w=e_{0xsTQ|Ys z&l!OF++#~K)_CGXaI3#P1^h{&*It;5KH=5C>6xh?=jvK&Zum|Q4{VVxK^kj!yd1~L z5B}M2E=X73Q8zwG0)kGVyG_9XYFl@tm1D2^qKsHO5WtIU+;TCdDZ;IJPJP4MfqH*? z$MBYkxBMA+?hW+u6^)}Ge|KzdemAs90z&y*H9`B0-^z1NxOD9I_U&8_uJ(+SASQK_ z&v@cJwHBAJeIgsV6EZfW-W8p+DD|3rfDaTzY}QOx9|?%IPQEMpMKPc-Ixy9%_53?* zSm5|Zo_m;kijiXXg?X%N6fpaW&%VwRoUXb%70}dn9B7)IM2fkw6mp{y1j;Ac;E!c%@0?Bgb~)i}nhOU|;Bc30p5 zNu7Ep}8_42<-0$c5L=oY*%U&ju3dp(gdJaxyx!Hq+REl9zgAR|+zsV^p%sHR#z z&J<6+2`Ib{C@qWS)bY#rFxMiEcgqS@2n^Yx`W9W#M5`n(woyCisyaCZxGg_0@8l#A z77d^Lw3{9SRfw}|lZn-SE1Gw0LY*MP2(hE*%DCDgBNGDXwGqRE*vN^;;R&ay9stG3?-W#w94aKlZaS7hfW^W#L* zSDA`}iE^K|_0>5&s99g^7xvK(g`45|)_+gC2dh%LM?HN8c|H`i2BSI0InkLGA4abbrL zdy=Goj&b>$GPn5hk4L6?n0uq)tX`7%i?#K#7x+9x@jio!V~+UXZLPipI0sMSoXmG$ zfTmmwyS^Qb?`&$?A`+~Y(TdMAcuc;*DlV*k49h%yLNWxEtYLD#k(HBJ>&GWGoGLfT z*>O-S0jthhKvBIvFn^z@E#=45WZrJg>zcy0cd`kE5XtjI9?(|aI!E}wuNzWPRpLme>9BK?&Q;U4_ZWs|eMS*g z-0U2IER(4xmps2|MIOmJEBkBgMST|Jc++Im6x(|yEqFiKnB_!C$>Lt|aR*iWum`DIFcj5+aPCpOGrV7pgQGAn+G)LsPP7?QpiBblwAgN7Cup$w#Q&h-Gm@00Ytfsb2r)Ya`3yP{Liw%2t;fS_v*r zF`iPvo@8(9QJkH0@}7fsV_EP>DMxtChh*#)#Wt6-VznLxi;V30;>z!5lIO_oM|Dc% zJ@2lV^Q;bfM>{3uS|xgV9_3p=(+eEkA6Eb?vK+a@yzEyP{&3OtVfjBUu9~o+EV7@r)F1kn zQawr_i*ZWE9KY&J;NcD&XKjgD7CJAle~X_@Z-Ez0&4!EfSgr@DqF8$BWt#5KSsL+& zfx*D3_zCe>w@x5dg^kGG;iWgyLNg@T7D=@<1> zlMbOBGr7}ZL8?2(-`TO#I(sTV!^@>@Sl@g9%1~gHqV5As`%+KK3`BZx$triv%~gw4 zV5?6#xAG88?y37sjthZ!=c7L_-yJOg!Bb+xKTr?kWFv<7Dx+ZLnIyz61~ao{6r^q_ z2^CqC(T;Zs55&D8QQ; z`_9|!xING#4`mcEl4=z)_L&wOtrQm5VxMe^vV9F@C|BopKFh64nlEeqjuLQ5*!&IH zt1~hFnYJGnBUoVR9Nq2&V?YV60e%RNK4FSozj$CfK}0l9i7(`}a#%=r&O5DcC?ZK6 zE2HhUgWaquricDgO;9l?YGSi%EbpYPxqbE}h*U`gE1CT=oZA1D+fdA=Jj7@|o^T<$ zzGE6Fc|wgmn%Etbq_$MQ`$5aFi%DHm!^WTucCvMI!4M^^s>m?#2Ez9TeH!K0K3zO# z+BLE+!FkV<#LU%NzryrcGIjAsB{iIt5(RcuqV$Udeb4W$x5P!f*U6x5>`##ZpKoN%5eQAAPWb_-` z%ruBw_27mtR=h!obVjdE8H#a^f8v!X%2KR^E#c{mSGSRLs(E(`zOe^erNT?{WPRqm zV4r}u6vcQz4R%e}jSI~^)7{9(e7EEm@Ta*IKWAV}(4AJX6tbn}??zE`u%=eFSknYn z+6(@UqF1iT0!G>4S6KUOMt= zqpwrvVrM9bGc$fB*EPR#qfi6;M&5U>Zr!#ZjUxSuC2P5&_PdFKk;#%K-!?|AkW_12J8gNciA+}7QR z#T26OkFjm*v#tGYz*znAOy!c#reW)InDTj(+QiR{km>3%R-jQU+|$ITZfZyZbrk~M zg!T1|d*da*omou|TxfA0RoYWwg-Mj^@+WeYx`Xp)e!^a>-$5~ZR87+2`;XFLY#kU^ za4R${8Y+2qlVfKWF${@6slj73G0dGAz9^Z7WE!}9Cw$#}-ybl@_ zW&kAgd3IvaV2#~c#k0o^jGkx%hq~zAnw9b)QXxG7UyJvv57GuPuww6?V`%U;!7{kS z+N02JxIU5sI60=P)c~7+Ge7F}#TR?US-S*leh=t2QR3Z~KJl*~cS&4C{XAbb!?8}? z0w_Tx^4-(Ruel69k5t^wtd_zmd6-7N5?J?_Q^&V8GFn1E_F^qPb%4@>U@mqOYj96l zKC@S9t?3d2;JCLQGhBbaQI!qNZ$0{_SJ8{uL7C5h#iOQwNSKWO_ef^9({N zuq=T0k?|hRC^1tQzRtF>$UB&}Jx{g=`Q{hK8>j$k#Zkw-Z$(JEA(qtyO)(UyiirFm zJOaXXDX1k##O=v`B)|7`lbS3df6(m?3=9U84;L|Id@8mT!lZcs9}=WZ7H&s5+;BBC z!fSCW=EznHWQRO1Ehg7p2#&(16#G&Q0jZ+vjZ5(_1u56EYBN| zi+7Q0-8Sqp9h&Su0#POTVM$kQ<#TghXe7V|P zF6Z6ozj1gVv5Aa@Um1By|Ek7cqY17Tz4+TKK_R81OL^*C)8?(&{X@)jNe&MkN0{n)(R60?PVeD{X z>-;FK8B?v;XM6zw1S#~LR&}ydMxP8c(}Vg#hwbsG4c-;2EneK)FI6*&W?3`7P|`p; zn$x&9iiel>aS7Kg0fisRsgWPjw$nRV z$WZ>*oEg~h;yLbDwUrDH^>SJN!Gh#e+o)un#ycrfl($9nqTU=iD_9iAH5DZQncE5m;Wt>U6yRh+gS{j zS=l8{l1+~OnQ?wgr>+uvQHIO_S?guOa5?a%%4?Sjo)UwzQr}8bnH$KgQ=k~E=^56h=;*$@^%KocBG{9yXCVhDG^P4NB1!pMIa$Fcz;1KvKoSxK zGP7}H_Wrt^3QQMI#-K!hjQ84&XD6a9FIDoKwnys94(h3Fqv!{1uD?fFJDWR6EQkhk zCl=ucncV3?I4>p~WCIs`A~oN5DHHvTRH5urKejR@se9CU5K!; z{C%_Y9Un4K)ThLO<(?%<2#2`btPScP56mOlH{wT(WmG z_MsOXWPhYUiHoESm=$aS9WXp^4HUDzc6sB5%zo){wyR;Y2~o7~eobDrnVaY%(J!s) z;3t>`Y{G@5?;;6R2S=DwCyWztr{A*{A~mI!x2DUysT ziD_CE^;R@|dTeAN-3WEaHPW?;QutarH zpS8Qnp*N}=>44xjb`0fJjR2v&spmmk**&M0Un?EY#VW}Ra~HSk8#@pV!id)olZ!)f zjo}h3lpwDKWy&+Uoyc3jd!I>X`)t8pZy)A@IAi-)h|wCkSa{o#?f9A{qZo?GiDfDcI0hwDfJuimZU0t9Wuk6v6&JCHjn71ms_WweaxP z=PY>Rz*nd?qsTgikoL~vodU~B-@zk+-TnNff@%=&{|a<|h{2uoj_?bHMxlpsztf+SG&n_y_i2 zeB4=)=jioVVXNDQE6lEip;usntzlH!`kk~fzBK4V9n%)}|%<7vGR-J+8VQ-r4o1LnuUO5p` z0d;P_F!!uK&qR!h=<;kBH}u#|NGT%}Dh1~D=ZccuUVZ+_)t_0v`@-!$ipi%f#u5vV zE9DfqXdUh(xZ3~uDOpQ=!ZLVkNCLP%v11-1Sw%OiHAi&jT>rFgk-}6*`yMRW9Z>)1 z(MI8r*vvn`cAJOG0~(s-VEbr!YNwLy)J=h|8b9^_x9-XDdZ&<#aZP5ntsYm6)C+QAw<%i0eWc>s0BtsP{ zX6zog=c-fbSjj{dwKxt-9L5-al`%8z=hXxEy1ot)#?>VI5IIhIMV;m~+;LMID2I)1 zdP%B-Z*c#c;LjDrR8k&XD-3?D%Q9!NcJn7!A+iDljA-q zL)F3&#$}U8aII^>4A0l&zT_-ja)eHYMuGa+QSNH3B$Q z776o>W^IE1%LMm7yd3@SwhV5a{wfBo7-+11(79}-Gyg!ak1RV!tgsep0V#+XdK z3p@U_nA|^%_Na%TJN{$;6tq_u_JG$pCnmyWX1VN?07`JRm)SI6e5vh+^X>6dLd@;g z*v=Ma4sG!!VcWH#6`1V3qP)B2w$iWKwmQ4_EfWq25o%j(5NXY8>VbQ2rmOxQ-z-47 zB;`rgM92y2foGuE-}BLumG1}wF4z2d$giya-rw=A!>|c-FGW8Z1h8|0>OpnP?yrJ1 zY_*XM`j~6$VZBCz-U0_^j+z@~RlouOh90xG<7=LbMOx~g6M|pu;`&|Jyid^jHqpPfwv$3e%64VpIl2I3 zs@)pqgVSVCbSTXEqj4o5EsYdOSvWYF>PI+9665m>R-y74<=k|+b!onIdvmE*E|sbE zeaCln&R1njX-T8tBkh93OtMNWdvxtUw6onp1`c`RyWL@etW)v;Jlg8r7a&r;|zR699;rb#QyURpwgb`iG(X zzMe9{)~G_HjwgxqwRJ@hRtwF{*P$xFP~$)^a-DSTzFMgu*Z$PiY@mpXnyAqsfJ;zc zA-=GpdRZrwgo73TEY=$1rJz{%3SM>+q$LTf%nc+b1gahizJEQXe?50qx6!##Xo^6r z5<=(gdpH=)w=mn><6m|=&7zxg)HvCRw5l1OA0-ft6TQE6&;UNhcMlo%&m}TSwH&(Jt7-1Uaz4QI_ zS*`9<-HGl}OLgish1<8nl`@>2NSNc*xg_p_seu>uje)_a@TB|>)2DcO-prH8OX@}A zpZ_qLgm%PvJ?+#Ocf6Aw3R32_?ZdIPj8sZ3KfyPDZ-_pr>U|~j%>38yG3sM0m?1Zn zyr!8U0SA}os#9qMxn2cpi|OaQD4dVUx4&Hz-Jc}E#ag;(`aVixjUrLs?JaeIrW0u{ zT93G6zH3~#`(&lD3H2befM1F2jxAmBH1wyBq>lJ3^tK+h03rG}XJpjXV5j}<4bpr$ zzWSc?5iFVpkxG@m8G*@Mg0OhvwVzhb@ls5gr+B`WbNXxUOEd)4vuPY$8O~F;Q_B6y z0(QQjXVo~V1m&9X5|)7DvyjW*yO?bbir1&nNzDu+`trlm#&WBid825(N|7799}Y#)uVBg5B7-+$B2&pmfZza z+O70GjIw7LvQa;cVg|MVRZ^70?F$Kq*V4suIuL&!N(~xHWGS}D)(rIlhagZe@OS^1 zv0mI=ynjRT_^-wMcZ#@QLJ{0CO*EzaLyG`~D38s+%#2h$<-}(9`-YRerh;VNX=?zV ztF|taw8wZ{P_tYkRia;XK}8^g*A~I)wXWJR>(v!gOh)8zSZr@u!`A2&ts zM@^*bx#(=rcx^T%@oA-9hQp8oE?_(Au)ey2xhJ*kX|iQm&gQHlRX&6p7VqO{m06lb z$7fU3F1Jipw)G%dUMC-4)6;D4SBumLWd?SEDX=wYEiwqCsHpdS^-EUcm>N*}HfW5o zwNT87YMD^Bb!}gBJubO}y*l$IqbW(!^O$x#3}K86r>rkJmM7e6PJM;jDG5V0>|NQB zufKn**~JnRl{Hb7xQ0$uZwV>)>nX91qF|X<&u_2Fs;^5KjZHM|Q1*`LE`Dpb{IMkS zpe{8UCHOSa@-V9$52ffTgJB1S(7`x_*SN7oe$nOgP#?3WiK%x=muO&Bgezjn><#cR zw+f4{1@`LcOY%RAZmx~Le{b&T7`XFI8A%Na2F3)G9*TgS2{w&#cdG;juOEglez{C0 z#z3{>)$l|DGZE46e&(-NmzS3ELyD?KYSki}6D_(pZw!+$GT`}|+ zWLY^%^nORn;4&YDiZCm!Eyo(AklWPc@#9!(YasPDAO{^VU}U{xn`B67_S<_hJ#1Wn zR3k_sQD+OlESzjwWj-LuBNk7#1m(63pRRZ)^u%S3=Pc7L@9Ft)s`AO%RYlMjcWTAw zN`_zbsB?9^v;z|`$$7flCnqbgffy<1G!2xPKN~t%_nXSHXY;p;6&a4PefPaAX)Uoz ziIGZjk*TqUQb^xCv!w1~tPsU5$tYFSJjDqg*U=tck7ap$GVYfqYMtE7bA<&pm7ctd z6QKGCN_8FM{NSZ_Hw#P5j#UueY*!n=)9g0GKBf8k}>_)-n3(XtMfL%-B>#2qoW8qyD^6D!Wz;Z#w2A zZ1pA5y=8H}el(S^+YSEl45#QtKH)DRAxxn?m|6VIqW~STgo^j&+TA~ll{>R%oc;?{ zqv~2_JJX;Gh zaSacrB;=%_oAOdVsztxaa2ri0!PhOXJ*IOc%M=! zaOOjNB7`>XE-xz6PFu{v_}rF*?lt$!Pfs`E`bhIr`@}x4hqQ@yhk#lB_juyBR?+O38>Dh`r1T>Zn?9v7r2nIhx-7}}dS6*|}QnE=0lcdGsp z{Pt$-G}@*?;aJ9LA~l`==8Q}~kya);;}#!$q?bbCQ|{(DkQEjvS03Ro7JWA2{XWb2 z_S1!A(S4~{LQM&crperdJ@75uTItzvR;zDX3lXf5V#IZl_tNJp*;-;eFlG43oxUt| zhZeVixihnu|Bnm##}UP|IiHaPa=2 zS>FiB*xi&9q8woN*_@RrR(*)_v3BUiH=^ifTO0Poa)P4UIzd$}Wc~dE%v9s-`I#F0XOMv!$;F_fzkPhq&EXG8o|<|o3OV5N6>~Fx!U`% zV{7%9n;d)i$Ff3-E=n#KLakZMgYRO#_@q5DF2PLDYMI({P5L`0Eq?!S@^W(loG{g&vo?KgX}@FIlZH~>!| zcsDXwYo2mT;>VG`9V6IYf@a{RJ-wBuk}4&WyU|k}&DI5OB|f~}2~>7c;vj6%6~ka- ziuc2oGBj+GuV^(M?(0`idS;dHNoou`|1NZA!`T?q^S|0bh}1#X;Y| z002<_-}x?wExoE6eV}?$^O@=_YyA4csh~>W(|juETQ##U`YZ0)_}zVioSvhi zYfUFsuC@Zk{t1X$wbJ+H)#SnKJN}Nlz|^yw=>#jEi%$3010r*huXK#(I zww4kt?k|fGyT1em?mzlQXVZ-yKeCFUTP5vxuLHFP8Hpof~F{B{RPAw)=l% zjeus>JuE#LiHAgcKEKUAtt?a7QpE`f^Y@z2Mj6$D|1unFE1wLZ87U&2o#}zOK1r;E z)F6ME=*LUmJZn~=F;0n}u}zjkVno`#{fRnByr+ex$9D$zysj_ql&h^2RBZ3 z)C0o`UCorD#M~7U4SUf$O+ufQOzT2-XbY$b;ZmDkB+|B4l1`>1*aPEz##Q{d_z?zktFG~e;C6rmHOWH zxnwQ;KG-oHqBcJ8j6&v#cH(OCbotrHRc|(1&tP6DB(U4B_~w`^P|Q0@-4U>Jy`^Ic z9Fpx)S1?3d14UNR8(Cn>e1+bgQ3YTFwU8sYDl!;87%8=s^D%=!-L-A4Ma)HWG>zVy~x8IDrdH7-Wb=4oK0eRkQwFkjlz0=X{<2TLMH6P=?E4;MOLE1*{N$^koI)2BlxvqYYPk{o zyd3+iQ_Ot0pzoPyg#1=Of^1ndMpF;0oEa2>{U z{>5~;?3%*YTm+1FNfVQ)}s)_7S6EOkZJh6${A8`iv^U&cH!9 z=Y;2GO^SCzZ;HQGMY+P}hPfKa*Myi>L5%YQZ8}=k09{fyuNronRHBUn>qQhu!op%n zIboAw#yu}!V$gjUA9?gOqLA`kR%Cfe9`TydBr=r#dib+lp*5YfLtflF{XAmYE6)gK z7V9fAy`U#&&(P>^75j4&5gvWN{nEr23JrWVtcV**$*|wdAGaW_y^ne0de~T!#R3me zIu5h(-}j&v4Sx#uJERAIdf3vx@ZHe;7C~$x>F~w(wQ3dq@)KU8WWRq^s^$(A9RR!i zHX7Eqq=YpBF#T7a;@xdg=YdCsPWu>BI3&%2NBZLALnr7*%U|`P&&;(fk1>6S-#`wIf0Kx-WuLgRTKdEi;$Mr#pZ_!AH zC?f`q_sM@5cL%B%jB|Hd#c`7q?IR%Be+us-0BnY1?vF`%iB&xU<<(6v`ub)+7fy#b zBK1)o!Pi*y>r48^Mo_(?yos0&P=7D?Uqm8*ZnC~UwAgCI$xT4wbNbjU78?QzGqX*uC)OMH&3v47MEU0!o~8fkVL9yoEF| zo_w^ zt#yx5o(F6?^lmqro$zK;pquik@}2>@xrs+zb)cLKXv7!+TE*V7_hHGTypA;8IU)LJ zaDkaay9QTP&e5@2-;MZ(QJwmQXx<6Vs^p({)j*GD3R$sqR>|Dy5VTnMv}vr##^^LK zx>+YD)le3zP70>GkC9QVvQzfoWd~sIi|T@2@eCCkXj|P8*1dTlKT^OWLP`E zn#-HT!tDQ(`V5=-=A~-XRMp^kp_oQhuzin2L`|35cziyC9JZM@lB7I}ZKRn)<$3Xp z#7ESoe&K9s4@ZJ^sdLVG@Ffx6A2xep+d|soc~&O_HP2_Q@?TBa50%DOy+zLahf%K9#tble^hfY| zRl1S2xlFF#?X+rgM5>J_F{*O#b$G9CB;cAi^q4*>>jOVab!F3Pqcf5HXux)Zd4N03n8A1>Xg=4OXjy*(Rt3N(h zmv`GZ=<1&KDh^dvrN6K+N9;VS*Kn#c#6t!A7XFz)XXsmlcw5`W#%C{2yY_HS%=w0v zK@Q)n*F|D*S56gXrZY=Rs7Umo_`_ZvnW4FV?jVp2WV`YB6XEa=;~U;PRl@G?j%q_g zT12F$M^}6E37HX?&yf7*@!l=-?E7o}RpK;^mHdyv*Ga3?_H%k4TYh)NNz7CCt83Mk zQqmuCUm)Q=*Q+VLLz>$Q4XD_$v2r80>6Bn0U2rafpq;QT&*G&Uo~ZtKCm5JIc&<4u z5-I-Zr%f3g&ZDy^8&c~MM)nf>_d!;^@9ezAN&`Yq?NWwo1mARhjor#SpWK)_gkVQgSH`e`9gwFe_+#-dnu6 zRd1Z!BBRkOOoqV>knHwvI6&ZYLC;p9-ZOoRd}woQy>$U%r66(Y63e-F_PvR%EXCVJ zZRUEV4qBIw@-N*pP|;2*rg{o&iS{2>lBejCe|V+;xP<%K4Wh4AWOpNJXZ|0X1sb@Yndgf_ zq(Pgk7*DIBonyvK&W=pbf5-Cc)f|E~>|}Dtu(XinedhN)hR5NqSRQrJs2syFQ{#j7 z0`|;7;nl9U3t(5zi0|LlLXqlJp`Eg1l_H>(*Y5N^`XL1=!B2p{fG+Aen1yh6)XBO? z=yZa$K>hY?8UGuVO$PHHU;9pJKdOG&xi_2f$Kv4&q=!GJqQ2KzWCivRPLh z8}hG#FXR}WqesMB+QN%+hMvd26L=3lMi_%)y8c)#4a_Rmqdt&?aa;*>rfIU$v*ZWk z@g`(kUh?|@pdz28{go4uSuHBiTZY^P!b98CSlV5Y)1MwpI>N3xe-iXG)0sb%6D&I6 zeK2&Da?nyga*r9fEDkAA{a$OdtWB7D@OB=~;n3@&wjk7tD-(Fj9EkOzEA*-q^5a{8 z>#sc`oi(2~&&%7iUaBF3)itxe=g}olDu3nVU}v!_7yr~M(<~mCB*L3u1YDHmD;!CB zz9IW<_a(+%?Cs_N3xAiVtd@ff@Q?fIJq;7;^FqOBJNdv(F%dQaVN9@AW~<1Np=6p? z^8|aOti?=F!>{&*UzU9J*#YcM48PznAi`4O^)vwzb%s)swZVbWWka#$HGgF0lx3=e zd0@0Ul7C8fF)*&m9-(G>M)rvpo`L%y~4qBF)Vfn4^uXGaVo~z{;bZ zI%&7wW#u&c!}6q2)$PNk6kG4_!g}}fWk(5>NHe?bdWyONnL`oChBN1j9#=)jm8SVk zg-!Nc;kOS-t~MM#w7O48?@M)B6WJ83t+BNfxJlC|SWamuI~J3bb`+78-}dyYv6GuS z_fsg&h>*@ggPp-N>OAVxdRm@o?`w^O>P(rNei}LTBnb~yOYOQ~ELJDh621TCV3d(j zm|h?{E1oRQO#zYT)l;POc>`VLMi{0uxKr9bVevk5+R19&En)S@g$$8bwDI<^esmIE zV63wr@MWzTl7b|eW9u!<+vFwiX>)ojPz>ZIJ==;J3YNzeHsG9~|9+~2v6EJp``W6_ z|2I?tJbHzW%wu-BYNexCI=}Ai$s?I^$w-tmd$b1f_BgE#G3kA$3;Nl@bWR(6@qyV( z*lO_M(=7~|`l6qHGEq`2048190kPU7QPx*uslcas<=-xk!t_%($kOFAtKBqpgWcf`%nGt|kSe5AK z(SI134r_f(X2=4EO=XgL8j-z+VTsK4Kl5#}Q^kabXF4*tEp=p*S*cp#LKMsOlg-sP z+9&JFX1hKHEe5t;Ch7QVDdA~eA=GSW!h;dXOqb3QH2!DkvuFanx}(JWXgK5Yo|z~$ z+U%||c4{@Pxr|RM!6`83T=_U^vT9S1omc7ls`n67uc7v-R2* z0^|;Qs0m#Ka;n;GakB0qF7yf@My}&i30l%inAVl`8((kdAQF(Jhb$YV4he4VG>~li zQsI&h5TyS#?u<}xKm$bB$fJwZ^C2V$csve=WTCvu8kglVIckK#>7=n9a0XUROB#U- zQoRK=dr}Ynow{ELgIMB`857S6Z#O?%rp>2-0CxCV};TKEINS7t9~M>-EQkbb&YDaVb|k(Qa=Vg>HGDH zJAB{zFq~M?OY3CKRvNlIZ%xS5uSM-s!gpZpO&@w69r;zJ%Y*ss$+jpm(g^(;s20L^ zR!|Y7_t(VS_=w$n)Jqb)tvFJXd9h5IWx;!D&5_cf$N1AzBHybwNZofkgiDSpPii2F z=*~?i*(T`>T0fK@oVN2&plj2&x=~)N9fd$qoERtoSm-X2JvSxc=760vCT9*oYm?lk z)X*)l&<$Y6yltI3!Y*2(w1v64Wd)IVwR4dx%bO+?RR&|Y%I(pk8o<_4>zmite_UL) zl|1s@o*goDm6JU(jzNlO<@*DtzaUs2j!1jy(oI0QJ{fEOHbGj(!V{9Gk1g;^=RQ)=o z9d+N|Ru#(PEKh#{NG4^;cp+m_S$=J812RHL+ku7zHa|DssX2znRnybxeO5PdD|g)0 zTYN=Ew0MXs>f#h%&oNrWOpNSHwL2JoDL{4ft9RxsP$BLF(Ml&5#nxX=V^7-uCQP{r zrQ3#Lyql@sN}cbkOldDagd-_n{O9za>h#ox2K&L9(SEtP!9(zpA(Mgc9?+Bynlbr^;1{JeZBbeIL%t z9u-)Ok|g_1LC^r|o^Dm5%jg*%r;<}9I>L-1;vv`<*JTU##g1g*s$xIk{0ze{=AADW zu<62m=X8L)95fvAZtSCoJklPway!w&JvAqR1in4DAo6x$&Pk z+dG3YvUESC$w`8<5wgOwQd}jBbr!vD+N=i2%I7CQw;<8x&`yR|}(wXXPQ1;iAssh)L;Nk+RMFNz%!n4&1higpsuaOGH+h%xLbMrh zTukHV7xGxU4omVSE9zf5yxcp7qDfBzQ;rH8@*MBYTb>QX`&q?imgos9T*fLd1kZ|e z?gW6bGKEZ}sa{F>Ja76EPsCI9)Dy!)oTaMBBiE_ABVBc3xXoW)UOQcqD+%@alE z299;zPP5S(DLb6qhP}np?Mf7;<3x)mcv2YImHso-#09E9!jna#!=!UMptr#4(40B~ zL8Nc9>t+9f_)P3x#N4}bFE1ZvBMas#$`pbx$-gNEq&k=gms_o0#ImjL*SPswy|XUZ zu>twyU(@mYrDk!L&~lTmI=}C67*LGlCIaCOaP(~YHPPHX=Z1~E&s>@Z z+Bq&1mBI0Ak+W+WL^?_XV}C0tijtga=uQVTn2PRy&wog~px8@me1TGoQ#)SJ=MfEV z`SSO{fwhe}d3d;pc(zMLrcp7TOqvWCoA|R7$%ONnYL*+?41JH@4|%;;RZ2Nh$;pop z!uVV%$&A`OkBR_lIHPMc&FxGMid952XkWK8d|#Qg<0`q1LG?>a|8I&NwCFiRq965t zu=dtbZML5q{%!MzlhKndgpnp18=FdB3R~6lN|D8QRE&`?b<(3C;Ro0Ky2XW`lH!> zdetG$kQ_RFk@h&*_y-LLpmDLfYi#hTI3ZGuck?d>{=`9;-67zSb83Wpm%@{k+6~B} z72|Da``VLr(YebsDMWu1T)WE+*GYc8bZ5!2@iGDsZQE#cmzaHG1UqPcmO0#!V}SrSEGeOrc$C35iG z3`(u)tWuGDGX}TvTXfcd(~v>30WMs46JJM$MYnR3ALyJaS+m&}#2u$sVQq=?CL z6R5u3odb6vEW+4aLSJ2{yr#0Cv$ARkrpel>uDI-ehD<+AjhIlvmWdVOSL2mX>}1bo zjlJ*-Tx!@_wSKHQPM_8Fb^wOFb8w4@~LSkIw@#hY2^a8{U=f?o63WZs& z9uQ3VY2Y6au_=rH`gfhx-RG-8oAIe3H}{kMxZ7Z(WtXZwGjBss*~Puz`Ivwtm8j8|B?Ido z&!DtFrF=xcA(p~9MC@Io@xuKjbef(0b4XHDkI7#Q)al8{_2jDJu1RtDX@iP`M`0*e z+6-{B0p!g-WL)--Orio3tFHAaS|m6u?zBX?AQ`RtuAo&oDQ~*?qJgd4{PCf%PW+|rO zuL6|Wa5^~Q3jU+4J>b*F*)|ic59Vr8LK?1w32e#?`~#w5qW-L~e52?&bk?v|>dU{; zt+lgtDEp5DS4AWH1!?CM%Z;tev-?svK_1KBM7ZiIn7{lvI%(C6HGglYAb;?CS|?54 zV|Us$EybsfiqUXvf?IIWiR}bk-_c15y;~O9IoAAr>khtAo*$B!r9n^h0gN9U>XQ#C zX!C|4Q{wG6)NQjWR`wC~OC{wNqr`&*&fuA;^e<*3U=<_`0Kpfu7lr)OC7vuF1%g55ZghR<|}tRfaD(f6?d zRUbzX6knyatDX)paubU+H2XSf{88OvmSo-G$N-Ak*9ic-UpUK3hwj?4C`nsgfNxeZ$7d7*I=M6(XPe9vS4q_> zVA*zxn}m}3wbBl4JaZn3K|2nzhh{{xTSO;uwu`uG0Q%DD82K2}xFkQ3Wnwn@9qsCR zCwh#V3Yjc6i3HwZ4Mp7~We~-kRA!T#%t*j)A z9W8GoD%w+ePa-|Qp_^$`711OQ>zra%A#!)BElTQ#%mCFS4Bk)iVz=+ z`M9!ne(-Ji<>z2G*a(pGx{!b|i5tL}3wREkgEqM?l;c?UFVq=EMf(?62)ean>q2D; zzs0`*&sJS#5E_l;HNt6Z}^XX0KU{nH2@;AQ%OkYJ2P~#WyymcF!C4I?Z zR7u=Ru4lpCr&>Gov0$k{gi5B6l`GcE3ro(Fs@Et#hkHe$%SCvK#7)Y56H&Nk21)oH&R&$si^Cf(4I0v-Cfgx(MqI-B{0%*N1Zg-bHY8UJbBtm^ zSbk9t>}NeJQ;8+POpWr(`Pz2Rj6V+8PYr`AKb)$1tG&~CbSydW@fYgV^*Ylr?fP6u z;@4P9(vVok=`+nFw@H*>)D;DD~3FE)BI zp$ge(IsA4Ytpp*TuHOATX*VI%aujfB}^tMq^5)}n>h4#$T?Ef z@1rQ6@g9;S9sL#-Rp^pySKWCS@%cUQpmWVluI-;~t6q4Jw+HL4zBu8b)Fs!*Ber$R zl%cb>F^zE~iK?)R5)K}?rx|3uWuWZ4LS`&wtje>_KQrBMQK{XVF#a$ zW7nT`<``qv-ce`&Go2HccReO8Go5d`Tv6YEn#A39f;*?i;ikneWawjk@5Zz+(R7J# ztc!U_4#r{c--S%b(QY8MEvpkPGe2y*Xu9Y6!(EK~e`G&l#qd@T(=lMKTLG&JVV{?< zRGczJ4~DZ8^$IL#r)V`9M&{XG7yYR7(b4K0*eM>X1?lpwq+e_VF)sWR?N!`hmBt-p`k zLg(a1;1fO8C(3pj=d@@ORHCE0cte$3 z-YEQ_ss?kGmBP}S4yP%+AUHx-K;E~l89#Dt=|p=e+v@Ct6U^iG zm7bqP1a1NkG`Y1c)`Nz%u-%#|W4ZsytA=<8&H?BzhDy3JvVY2?UOqwxYP*Tgvd1x+ zAKx-NulDXdF_bb&6qfUYZ_d3clQ44?Ks`^nOF5|3&&*iFv0$jkFR&mWKQaYdc$Lql zdB$;{SCcs*2p%n8>%z(1U9^A0h3ztpZ$%{POK?#I03jUV=`(tLha(K{(vw@b#=Po*=bW{=C;rEtIhgP*-qM$jXytt&5jc)OJ3F;|uaE#Y+29y?k#c``0s-&;^peIXAc~5n*$LFuf(x&G&kR(teaxg zRm$acwYAqEuZ5`2ARb_GuHPUGHqSoTb4`Agtsp7>>sHZQ<}TfVmJc>c57=vCJvi5d-N-s$w%xvU+( z!WrQwhe-*@Z@!AFc>2QiSCCY#PQ-Ol-bxzJL9~g>IGTpBEpU#-*v(>?q zjCT?q{jM_Y+9wTh%r-K#Ut@T zYjT6-5ZM?*9S+u%4kahpa3+DessE$Q)O}bazFeZVpF)gupKomSIk_Tb&AedC$;je# z2VFy@ZJIkaHu2LIwH^$3^eCT3djOBR+*#*%1*=+sN->RFNeYS17O>a7P+6X!Qcmj| zNoK-AVSuz(vDLM$xignz!Hwpy5~(}Mr9w|OW7%_dj{f7Bg@`;cK#_r!7l7U*QB21= z0lSj@P!u&Aa-KqWM!LC4>g1D|Q+mIjT)NZcpIn;T>HhJo`rU9ZY8Gz+r0(4D&80I=YGUw#u2dyAc$`lOktps+pX9jPvhA3Iq(ETIA3RWt-4LI8 zBBz3#YI8x9rRy1yKa z@Tif0!<%SjgyA~r!kMsAT(LtI&M)mB5>B1)kL;J4%7l^0Qyn?JA)*3hyG#8&HQL>6 zu4uJ}A@5KU;?n!CgJz)BTXu_B$qomu>v&v_KyJip5pco(RokTAt zS4SATTcl$dVIu04PDNo3(I=s~X*ShfDT-){)KT zKA(I}Z==)HIVUH<3=Q*+J;shFQ(PbGn|E?N23|rtfy<5x({6F`$*j^*MMQ@8_NFkb zxvQ(IDgw%Fw#FOLLh1-SuSXj^@D+)26d#hBuhFX#C3Sz-OUdQUtG+|b+H1?8i zG$C~Y0yn8|>V^iV%mU#3nP?ffDXTFdi{YxA&1Wm7oE08PizcTo=SufJzdh4YK=(#- zT$n0O%8VtF(Gp`3dXO9r)9jas-&*={{gjF8)O2w6<_xW?PEV~{CL$f{e`y5&i zi7Y$bk9k0hw<6gsx3m12tJf~R%#Ni_k*x6$^TsnCLMv}NN z4$WAR#0#m;q&^gCq%6vR(YWn3(nGd8Y?tXRYs)!F9v;C@Q>H45s_!Y-j@wjdl|=e( zl*qs8nH$mYVpdh-ChbDD%h*#4(3-@k{DW*EV>gI{Y6^9wBLY_O6+KuW20l`2JKpLI<8V^Nx$+ub$}_w;_Y z%gu~}LdZ4GN*X}mnNV*D(YS=MgBa#scEnNV#g5I%+E#!3RM*+VC^c|%T{&_|b>xKf zc-C=RXeZO=+P5`zKXoU-m|X2t$ap}Lnd$NH!v*<$YmU^LxRbvaUpBdTt`uuE2Rc<$ zvhJDxV*Gr&RQ0I=i|nRi;mgY#p{fMM(9vTNl&|Bf^OuVO9p2>xj6Lfu>kIEfjBbbO zJEgbOq_HIMylp@cU3R`s6%8Fu9n!Hb5w|a$>h8>K^(CZV6biqwjp!U3a*nG0wts}n z*cr`xfV>xVxA$A5lLUMQ4My7cKZyTP)V=^B1rM(u!2^%CDch&8Q9SqY?({aeP2lVFOl{M2T$CU-Z}`d@Pwwla4HqW9s$E;IJjK?6~!w4@B@`X|aukrp@l8 za`C~KV$#GYHjhg7%P>Rk4U_zr$~9IB&sUtRSMJ#zw=bSSzv`+jK;y<;i<9v2y2JTb z+`PEIkKrMHOzcS`K}hnkl~TA+DN&m61j73Idq85(jtUcStj` z2w~U)A1bUoBrJ_`i1I*{F?L!H)`eotPTmQYyNtYyJc#Z+czAX#G(*j`{v5$v=7wFl zYKRSL9Dvdi@9thJ{RqL5&a|}d)Eeo@cvaaEpmq<7N}}41Y9}!cF%T+u6FMxE28U3o zvx_>ycUNg%h&pnF(wcJ5mq%w-_g4pdG~T~)I^NFf_Y5j%KzVLF?w)5Gv$3(kXIGoR z=l5p7>p$rY!~7q&@2N}6M7;WvWBFggvQmV^ybTwC(t3#bUSIP2mN9ow<`|_M(NYnr z->yoXOp%YA;@PYtzsczivi}&gI?-xZa-8Kq-9Wu1TPai_l7u08F_*BruMY$@DI})Y zL<4&iveVc9jDms*;PS~o6vNgIXQ^yD6jZ82W9BrQ>Jqa_O!b`Yx26*?h@sB?;2#Ye8|i)nnzxEjxpBT0oOxqgw>{(`;F4qIh$|S*`-Yf9v@>M6J^Q5;|MR&mg=$;9=pHTinDV&?Vi4CcnMe`m`wj$g$I{ zbS>F&z3G9B$RNaFw&|99E1B8x*#B^0YU!U>P0S0p_G{~FR*YCmov;K^$dG9V!Q=UJ z6_y2NTBXXrnvh=4v)1}CE^V8}O%LAK69(ub^`qHbqlm=CE0|oVJ;pR#qTo^O1BC@9 zA3f`>cIbkDdRZ_1TP0qA%>a4_e>{8a-Ck|VzQu2QwNdCgHd4xzbH!b2JK3uEEpF4S z(4g^^az|qy5=X-U?u{w7$vRn6wd+j;0^Xt6s^4ROT2?8bZcZyGKdB{1H-fr+@3F&d>Oar3{G@f}x&4)sIJ{WKH|=eAcxmS*|;dsnTh2J!8rvYJ>->MUS2kQB-RaJ-r? z&7F_dX0b|QlujR#9r+2y)ORnuh*8RjcrWtcpfmz9WKf*>D0E72Bn$4-8u^u@Za+Ra zn7>hT;;d5t+0X1%F>rL*KC?+~{KJN~CS#%HyyY0ZcwRnSNLx1b8BKSwDEs&U;x&KO z1AF^`_+>Xm#U_L5&~a%`IOTr$FP8fs4AS+IQz^-{@%bZ(1q1U)vYz_0bX$5Nw=k@U{GEJ4-bONU|>S;fS-oL%|d4eWjpCZBDwUfR! zdwz@|s%|l!>k_wX4zU8==BffN%~i^k6=!VC`NPsPq{JDtDW{$9y?`^FH4gDVvyQ%NXkX! zfWyJ9oJsL*q-h-HyVcp6HSbwVZuOW>^`@!%*fR?ZRtlAlw zk}~^saK$H(XAq$tYh{l#4I6iP_v&p^yPz6a$>kRa?3-!xz#gB%0@k+RnYA1ixb@_uj zwTz7x;xP)p&}uwgmc0LJZKF#>Fqpd5@LF$dY-oFwFY4A;d!-~|IZ>&*dv5B#rTG89 zY*1oSQ0%@pTgh(f;ALOvson6heNMm$FrGW3-k80k;Sje6`L7_Yf^FabN5SWh`}Q>s z#szI72|?1^e>F$3yL+)@(C3Re8`4Gab5lHRbE|Lu{QJAT2ipHJigw;xrGkyJ-Ew_! zP)OzcvG^5pF3w9Twyh3FT3N-EjOSSb$2TXezH1UAYVQNLpz$?n$^D6b6c}y;2jAz- zhM}hIYq7)8%IcHi1L~~d9I>Y3EE|{bhWqy;y4BbzlO9!Q;gcO#aF z_gPOnriCgdkmny%r?J!_+7Y;ubNT{)3&(YR!xjyWIAv0Fe*$e?2#Rlj$4S#jUsPv{ zMFNh^_sC(;6ztvjp07zz5z$z)E0P`R-tvHFTmtTe3s?BpjdN9Tlay=4EWNT($^amE zMnN1Y77RmuaGsSYAB+!*ICLA%ez%;HzDh=ib%svrBA%=`LX(^o1>o`Z+m?aEmREq$ zpBGpyFVG32#KWdC8$_KVwTLU)^E<3e zxLhowue|~MEBM2Wwi0dD)#9(Mmf}~gda+&IZm32^+xcn)Ee8%-s3e!+VEZb?NMk5- zeh*8_sYw6`~I#zfWRy{=v&Wyqv7KZRG2x!YNkVqPHaVPxXjHAn?VinGuFMaxF3bB$1zWD`KlPeD3;L4 zF_LWKN#>ManKAp#k72T%u_5=p-P~ZGZg4ZN8fXWDM%})L+rY|`;UpqfuJ4FOSjduH zAi_^X%4^{iLrv7*qaryHEpsS8$LqAT$)21Q@qwIvE8!DTF0~g^?goHw;=g~5qT`YG z*`WE96|iYLQr-Qeb01G9KP%dE8lJbLL(kZ4k|x!vtJcd7K!QJ`vC*ZdnFzw<{J$75 z#LWD&3DI(0mnZW>lO91(jinb3XHR7YwJTtsKjHVg28p^Yih>D4|5#}`=h-;VB;x@~ zhmHE8qTN~ssiRwmEniOpspmyRe#90@RrxWqEm$t7+n!XuyG$QX8Sv@cpl^eI`JGfW zx5`fYk{lAGHIgt}^UvrtNmQX=w}&!FjPruKCF$pj)Qn=3RPn(u>yMDl6~&+w5XRYW z8ywb2VE?Aob1cXr!;$SQWoT$=tUJur^Q45wT)K~`Wyf2X?IoF<}77_ z=Fgud7nsSQD6ZpRKqDO)(ZthqJ$I(8vo2{}O;m%dn*rLl%A-XzKudiv0g&8Yr~U1F z^{cEe28&`}k76qg$=8$ToR1ab%G(GThY_iIVi7sY)+;G5V~c@1@X1f?qa3Angn?hV z7%qO|QICzOX7nVv@r+ikV1R>_siBKF8=aL8>-Vh$ltK~XN|F(*rMwMTB3OoflkQ7;SjA?D0>@U@0|mOgxIWAzv6``W-E4k$CXc+YvXXdE^qoc(^ zSf3PS4ZyhI$RcD_-Zb>&g`eHZD`n{1JBm1J!J4;N)*mjvXbK}o`6&Y zDF)cn7 zZCA#F4g6$n$>MSL;DPvDoyKd<)Ho)yYb7Q>sq9aT9PFck6HOJ)^NVMeaX=UN*Do!* zx3gH$8$y$pKAmQ9g>QyHnZf-|41F^`hkYM_Yy33e*E<@UE^@w(K35b=vDM=xY<;m= z*$OLNzoJY9#oMNll{|#~+^@ORuko5*zn&Z;-rAfa^-ff9>2eI>U|TRw18EnG6Rk(z zERL2T?2I<@NH{$IVnqFn`kd6h1xw@t9ethMUG>>H`OpN8HERHPNmq=lGgLOPo?k6yG)~olZs7w(;^%DWoFL4CIQ4yx0?OBoQVsS1ND8( zTmcWhr6!>hC71e9`x)!xL3^~P4V7VkF@&2YikJj)L_&YsSPP#*fddmlD1{!{q;c{R z{{nLWP?ArO2^pEV#&oDZ>ZG#pT2sE`qwRl^WXOhDXj`(*miOKT$@(gS~O)t+Z+p0|>#ix-~jujF2 zuTzi^+Dq2}h?Fa+F&oxteLx%TH3U^yplSQG^0WbtWY8?G3LF$If86(RkS=z0Zhtz^ zqE9hY+_jfmla~@P|89go%Pe*j77jStA^2VuRwZRPJ|D|J(3MamN!Ydiq_p|DC{3uA z$iotwy6613e5!TW)RnO5MTms;7x{>siR_*Sv>oq97}`X5czH(R^@(p~ zJ953WGdH3;Iy4htYnJ5K9+Q4|8J-?b7N5{82vPO#mBiUy;jo(*YHJr-RSuu4a3pX_ zW!%FvB~BI|WO|og6cFfw`J2)yzM}(QT(K(ollK}jW*oAJ`K<6gUfAvL=u05xjH!G7 z4X~3YJzw`;&`3}oiD$gcFz*sEN|78QEB)(*jIo-qL`!{6H8|7M@_3chR+%!zhHbBd zwzphMHT0>26F2bf=ihsxM;Fz3y;+t)iAmJ_(W3J0{vYW)xH@+h46N#;<3dgm$VYDD zqlvskqfhg~{weXPN$ZvUq=S3!d%~H5V}4SOyJSL1J<^0GatJAN)CUpLEyhf3jxmr} zLR`tWYICb%zx7g5dLo-h5pIf%m!6$b>&x{9@{vyvbIm^zk@(H;HC%@>NphwLS2{hs zHlq&?Rh5$Jb1QXO=QHX;{_>LZIGc6XUv1B^Nx=e(N|8TNMoA__{GSaBl)t?(GtGCqbmfRZ+;m@4 zDF!z`BP%xIG3w9M8nh4vi8c$M;B4d&GF;DgP=A9f{Uzj>eJ%e_>K=vePowdN&L|UAnZGvJ`3YY{S`c!2j%EGa??d9z#kq z)(6XQ!(-Vl)!#M!G`YlYkPDpO^G0&Km0XNCeJZqwB_eWptIL0q-;Jbp1qgfW*$iNXDD+;bphU35y>_keNil%p9%TtEhz7 z_v&}LejcjHlwU(!V-q12zxEPk7W(!bIH=xrKHcix65{ zJk^S&GRUXWoGbv1ep^OG&q#0Sh@0q}6S!;YSm^AyBk%hc1IPS5bY5NL=gW*Q^7AjT z4YigsiO-J~;DfjLEU7b;ib@%lsZ}QKACI`%(%w+8*>>wwoY4cQdzrp`xu{yw$|?g# z6(msz88|5J+$p!39$GgTn?+e5TfpXcq6N_4c! zHiHr#t?UMP3O)SH1VaQ85mkjs!9;B&METaXmiAJ9=O?k(r@P~qJQROY4xWUC730X_ z(}O@1i-Y)z+v(?IDZl&YbKpJwZp+ca<(b8Y#FnD6x`?=fN-lV2Jc!Z1#&fZ>tYQ$d zj(%HWIw`c2kwbc>RvIqEpwe)Cuk804ZE_zU9JCWXbP&UblX7i^^m4F+kK#?dI(SW8 zJ}c5o8;DhKfz8MRsO%tWC?;+{(hBq{-dh1JOk9@GVmF8@aNiSsZEwQ+G_i8xQ+};r zf-Y!t-ih;7A-kahzoJ>CyaoVKz*Rr`Wh6aX^SSnWa}+{jFT+66QM)iVO~Fy`^$E5* zKXDTujeRAN5dgQ($D#v*l(YgZ(cJ0sXAwCD;GIByurvVs;U3z|4MsSuk`xCDK2Ug5 zb)(BxERxbBT}J!TX{fV!?T9Ehb+$MF8VRQ*Df)7JHOg+JpviMvvWHz z({6EX)c$D;mj_`pUD7a=${?#G`R5)!ijYd+qyDWA9EICAoOA-W*B| zMa7Z*rk=aPbbM$%GUeIpv^k$!vRD*rr=!}=Su6<1+!Nm1vuZ2fXdTkMc03iY3;gWs z+__x-yG!kO6E1QqIXQ4@@io#vbGC0a{AE$vFRgbo*;?jr`nv)dtwc6Vzjl%~ZU1ro zv;NJTC1JcfgJTFAS!N@)!i7I~;T|6DV5p1BJh+8TplRB@G9v71WZwbuV7*7obr6tkYCEKL!TU zI>-UnEo8fHuS?Mn^n2=m@LtgMzwCA9)Gu_BAT?kmsrWfOF@B`A5N_?g3p2)ge(;p9 zODk$)S5M#kQI^8ex!&p1(3jcj)Rc;e$wXr z592~jaVf7$Q-3h@?dSM8vcqgbxFr8#Jl7r7obs7*D%r{qG$q3KrlR6Slh?8XGpiep|ia&vE6qLh0;MJQuu(ZYGCYo&vklmv1RZ{+@}`O2Es|H?_(U0)ge zDU(R@yj*T&WVT0wp`^~zwD?<#;K>w|InDuA?mu_4@0NEdnZS))H<9A<;(I|F@Tv5X zxATL38tXwv0?W$yH!mQ#YXA74NoFOz7P@!5Fju!|c@_w&q7<#LJj+NBiqh6psDJnW zbe;Y`tla(se*3S(uqHs50U6qun@Z?IoNw6M8JCfZV4YFqqHQ>y7I^&HZ?6)iRKwX~ z6f_V@jsr}8{@0Ff3lgc>Ub|!xzW4jrVmS>uiOeu*Ae28olhe|9rBIZ<9PlsWkSDt@ z*)$mbwJ0#-aJwObCB*ToCo4aan`9)XxKSCFdTjb+CaEs|JKRhv?#v}z)h~ku_Wr14AQ?qFd=*n!&HTmi>FJa*8#X=o2h!pKz+rpN`JMVsNy z1hAD(hnhBw8n$Gly?(Mq72|RbLbI5mSC!`IBbGJ}>hr8l3Vk5{B9I#|d{ z%{mJ6{+0IvQmxj%{{`KywKQB~jPc5`-3+fS_^Dy7C8s34%uZ{*h;>^1kvP&2XlR+D zHVTKuhl#L9Z0*aokxf5Z(suaja^ABzhKw>YLr7l!aE>Yk4AbqsZA>QoL%gy$KA9^ri;1wl*`es$P-vA4%*Q<_~H0r&{&f(~e zUs&Mefz57w!q2t5ec-4fcefoGn2q-ucXycD&AT|j$u)EK+= zjP5;)fmAq0*B<>kw#cj-EI4$8vIFZ zfmeNeT<=K<)JGV+==iFXcdAhG9FlF>T=4s-c5%2Owm7#x?ZP!7t#eniZQ5nVXZ9P> zN}Z|&xW~vKabdD<27>~e7^l_h^R=tfA>{k33|(jw4W+EYVk2>;Wb@KR<=ysqbg5MX zAK`kt2*wXZ^)t^uRc(ih!nAhM&@|?9XN9hWJ_(DTwjurBxgdD0zXG8BS$0iejRX{E z`x)%;TFn*xy`Q%e_FfKN4!5+}GdYK=t$Jl|W@wtRJWgd7dcFMm5?c*IB!#O4ltfRu zi%(SSEYLX$%7+M3`wq_DHtl&uWNqOja{;18nhnd*6?)xjQ|&m-C>D9C95XKN5E^9% z2u3zNFw=0n|BJB)y(t8+CK-Ui(wdmGW{u{jKrR-uXv#&M+WZ5zQbkrKSAg|3T$|%1_1NWJwCyfJ^QXMz6 zX;(-ako<$_<(JWq;{SYEygOizmcJY-ucR3{M)p3lhmuU!nQubGOYM4w_2L!P)i_hbT?6jHSs$ zr8*qH3gxH3-Nc%jsXVfhstvUJx}IA(b>mtiv1eSWX=bxS*Hb|w83H|Mv?T=RJqsI9 z!@o#z}i{RuX|JtCsK*9%?*+w59m+g06mCZxn z@a9V&-!6<_GS53|Ff35|@Eh^wHnrV7NzsMnCnU^D_+%yw(ZY6C)Cdp8F9(k7scu@9 zvpM1mgO4U9LVrOUZMVB2K&BfHN3SArrBgCA{KT7=$!xC+RJSl>ExH3*CZ+k)ms6-g35aXsTaI1|u zo4m=0*D+=^3_m$z^P0;4g-K9%4k*uenNJyYxupwxuOT z4Loh?lUU5NnH*jBuI02^AT6v%dY+q_{+r`#3DAMWeiK#{>apvO!C-W?Q?qRhp^-|) zQsVMam2hIi!1kuprlMs`uVVGC=_4Ig?4g2_>3nWuXNxG}akIM_84~0d{WV)dRIePH zt&BIJ$(r!4r_NFcqV|LWv%@e0WQuaPK_XV#j;?Ax7-!^X;PxCM+SaV6R8sp(>r6K@9sct&tdM^C^lkS1y z_c{6+k?mrMiw;qX22H)Pv3%_Bx7-eJ6clcxN->*BCkZ$<;$u#uWM? zI};)$DGmF8I_>e5!b2MWW3=9Y&>!8v6||U9YxA!`Jrmg-s$?y~*;5ev6VTBv#c_WA zIM+3I*q`3Wc#i&E0twUUqIETeRaWNHHL#)y!B6D^A8q$zW%vm!Oi50Ls7e`YLCX2I zh<)dLHbY}|l>(HmRoG+gFI|6EdynT6?6h`v0HhL=rNte|&et!J^ipd*?g6NWRcRLL zQe5dRCy$>6ZtA>PVvYhk0<(<2dQm4+w|vQB3nHxHnVd6*FQD^T%7vB-OA$4BXLxaA z+>61lVobV6eP`=KIayLDjDXB!ZF0^^E+6F!Z9~06co1fT&Gktq3%VBR9O6ey9?Smkt0|=Jp(OmTH(YE?#Unx};SI+k( zhKUiQ%19^VC;8EF`fuw%!$1$dI)xrb+R(}U9CjG&&~X>s`gTeFT6c1&t*eB=P|o1U zvb~_-R3aPYhI@tSGj5$j%e50qIzPHFv}RA!-IUe@_Q8zJEIrRGWTO6)(1n<*TtkUm zTCe#NlAUiguW`p`;3G@%Mn$l=08iLQABbG<&vp$yj4lAW<#wqsW>mLg0fyS zIg(XjV!{t>G-Ru+72QZpM>}TRxIFJvmxGn0guDFV=)Aw!aK``*SqtX1v@DxW{IXd* z+>4L&eJbMk98eJdNjq0fct9#iwU8yJb`Sl)$FGQ0KwK9ME;TBH47^^EMB#@f>G$DZ zjKzEGc1HHvuKLWZ;$IY2sE^`!fE;DbH#xX51mcBgKGWS)OA@&xvl+rR}=4*d(G=wLov2(eB901)SCClPigF@`z7>9&938}P2SJJK~tevnzy7mYnp0L zYjmQ+DR%WvCZaOYrEPruLO$T#3mZ$npDd)Wk)E zHKCwK>g9!xZ|#><#TQjh(mSihRk?fFZEcUp|MGM89;0{F!#Vt_W-7PqU;_gtq1lJad73<4y@3Z&WXP^7-8SjmI|65~a zWhHAQP{K;oBa>`#>#zjlGV49rRjb&Dz6&r9!Om!x6;Aq*S(pKMb3}?Yh!G z5dw*|l5vpFB^qrRD(5fFU>S|v)_pw|u8|jCJfHB^D8-_`t|$?yO(47`a-`oYuXkn9 z)6e{sty^trU^n0K0^1<81>PY~7<%%>)UcuO!kFXCEdr^a7J1|m5BE=b%X?^oHO1A2iT42{l_&BR-K`Nyg@z9t}^~R65$rSO?^CAg3 z8&nha{A7Biud7-04mOQm=EB#TVzCYtAHmH^v64%yHbYlO*2>*t*{k1BeJ)+=(SFT7*aXJyNe=|cOeEI$|ooo6?%F}ti5PXxvVySxL7 zm7PY^aoVKZ$@g7a6glOT*skD`TRfEZGDtFm%}MY2$aR?rdvVYy)YXs-DXEeHuJtkR zwnB3+*Rs5~FSv}pDt{OR06{{U)a#cgig+YIVwC~AsCx-j&)*TRS1oemvpwUo0=99& z+`e+M(bY?~MB#*)oF_%kuNaXq-BV9JUleT!2_Kjxmv+Yqt;4M858{ywS#PDs;5|=|6rqR^S8cU3h}=j%+aCV81U%2x zskX(+x6I!?eM9BQYM$t#>LR!_lc<;;tbofGQ~K8m0LJv_kZZQ%I*j6PtC5wdWcYKz z!@OAMRJ-4pXNl4NU(_^Em%+;!YZhEqdFrV&@2*Ohm?IPa`$hqBM*8od*uU*r0@S3* zP^liQ|J!>RNLWzjPLK??p1)wQ)&w4@mtw4@@DS|PQQ(N8CCpHaTRqVQ|sI+ z*W7fCzU{%QdFSX#_#NBeJOfp7(ki}8wO@;Af|lYN%dP2K<)6qsXhJ2?v;mH`U){AE zcx-6HVzNoi+S`x&caPL1tOv#z37g6^%M^+p;v@Q2J_je-q<2(JjC~lS@rCE5#FajU z*EKu`eE!zY)~hxbau%lEMR~#%KCcY3y!Fnl3|XYTJoG42t;%P)Ke`G10|Ty+X|LLHabsKPp4MXY?$ji zU0t8dri;N3ouBd&AFRKMk8<=Bz|&xaZ)rdBro*pYO(4-wqg$f_D8|TZ zP`IF^Xw!FVRd<^{;ApF>6IGt?n}1x-c{?52PDfZsO1d#Jq{rgL zVg{4TyBvi3>JX(T^G6k_tQwMSUKP~Ir4sIbOdvH2;S7c0f)!*tS_S}*O@rCaNoq{- zsvb`5Lg?g?5kKd>y!05ef+4xZKr$9ov5>fh7HYdS`^8Trb7Q051&bWbn_(_99iy+! zTcXR^hSo$@LxQWWo?2Bokv0sZr0HG+_V7+i5%`JCO(Q-zauNO5NhRWEPMAwrBp-yY z-@W|m#jCJipQ&O+<0faQyy>!OgAQZW_ut}RIfi_D&gM|>$?%J4gOS!pyHc|j{F*QN*kJf zp16HYlIktS$Z(oddUf&CH-``w@B-Oc%cr6@qFqPcmR-}Gzv8Tu65>1naI%mu3DX8c zJPtl+W$;541BRo$c^wAGIfizOCi~%oJ1p2FIrtUKZqYck(5q@goK8iHz5C3^O2Jco zG#~~o_m_oEkVw>-XZkUeicOhgi<-g)5Eys_`QC26k-xj15t@7szh=Yd)p@4Q-Q_bU zKz5}z$%Z3*l+AbKZFY0}i>B%wjFUh|gM;+Ld5(sw?zTK>c^smY+8*X~QD7T^G>J6; zau(4RUQ5`azilyKQ;}ztdyl~-*_4#TY(%>A++S6&>1l2pccDa}RaGp2!pSZpmGx5=|=*mT3J@N6VkIUbRLajvXt{c4x>NoArT zGX-+@Tl&6YbTqb=j2b`ku*;NlDSSx7ok>`@xCE`DP-(5^npD`}WzqVtRIn zSD4|bgBV&)pmEMf8|9o)X9KJgs^GHngt3FwTDp5cB-XQ%F%dkCS!krz+H&rBh(1h` z4*kUWxe1i;8cp8ZV_Tv^5q7yh+;_f(_c1s!NI*OmD65)aq#T%JiObp=`6djT5vaLa z{Ri;k$;9KRqWHP;i<9Gp#2qfVNbp=yX=Y+UqI#!4u}Mn8SSlRs0LV-*(u^UMU_t3( z*8uTz#Up#{F|AoD0#1AHY`3g=B!r{r`f#h`nnO}O%4lA5kBhwE62!T{@NB`W8*K>e z{Bh95A9ySUGcW2fI8LeB&)V=xD7g_T`2*-())32xwtTyU%Cs0#319F=7d79W zhkzX(l?9iTigeiiO5^1H|IT8<`CAF`A1NJAl~%Zt)fDyV_5&M5KDc2V_;0!Xe<}t5 zm=oyGzZVP`^Y{=YGV*Ue8Z`eXAg~=4kW6;uJ@DFHvOAXYL?t!;iLv~3-d}hHS!oaF zO7NfmgYRUh#USXf)G`Vvjl6(*<4}q?Guiv%)+>*H%+eJl<^fk7t@dx1u_bJq_ppe4 z%7T@=TF+y>bN$jKy{q*m$X^ZJvl{7>yk`v;Uo1QLjDCXlGdDGgH|Yi(7};R;{yvN7 z=iXUD=?w>2{W}t-gA%Z`9ByI(B_5JqP|$`^yHdR*Qo}cVMylQ@CJNn!&Pr+A$er;O z-y~VYiLS8ny(b8+?GRsBBMteo@p~~u7=&9GyFIHDGmg7Qy+_V9;LVjM#|l=}NbGTC zUQQ7=XM?!2BN@eg2|r|296L6%VTg&01nW5uuVy7ebV&H})1r5~)Zyz@`@gY3;<^ZA+cOXU8IMC z)eC`X5yYWsINN2-qKQgt3?@jUq$pgDk;=v7Tz6gc0Ff%uburCL#?A`A<035ork$>g zMBJ^w>UBiN{W`;0Ak)v0LbpuTt2OEP(t15N;_c>m7YV!2Z*v_!H;T1Tr0F)ueF&@x z`6kGNYWg2HnIjs zJjil`AuglOjb1)cE#E3B{@ncBHM%1(%;r&{lO$V&G;OlKdQ!EUb69zLP>SuN3`NKf za6MC5l0tt(tIi^ws&(?{p7M!UR#FI@uWr3g6||VY2XdZ8@IJlUmtW!-=oAL`R*Em+ zp8`;T5^-}6qKi4HgV4Ce0_#a%F?uDY!GIVN`CTK|_o0*)&*>f7?>uT=>BNRA3wXpd z9pYf`X1CX;X;4W&$6!@c*fcPs_@EuVYB9plm|pB0NFw=MpwO;l;sEc-rHu`pJ*^~? z9_%gsNGrN0!M@bLD^s4GHqN0wtrg<4sAs+AX)~Qv$XPn{T%~wKWagKR(pQY+i=iGe zkxFhUhRZCK{USp-Aau2mO;hA4N^FRTl#`(|bHCB?O7lHY zmQ&BB*DNWyu3dYNV4?8HJ8#3)&%kGcuJAz733B1#nd1iirQeKx(9xK$D$NY3Ywq)` zhJ(xu*EN-K^NfnwR}-x_rZJCz8y$pWlgIana|ZTa)20H{tj1%^$&AeQ(YVVRBBW#q z(a=XxQRpGA;;Ta=Ww-f7Mzz*a!{&$`%I|=LeZV)});LONd2Fnn5Z9Qkw9+s3jZSTq8LI< z{#^sLt{1Al%z|pqhr1?hQV5S*oSG*-;m~ek(p%7|t@tjoj}$a7m5`1dK2luHvdIxN zK1|qQscABns=2sq(e6EUe7#=et${}zV_L~inm0Wg-;Y?oc!4Qi=H-$U(zP*raLD#E zJ?F&IMNKjyvvgE{B&c#{i8+V_QB=EcANvS{wKFt({~(#ftV8^`nb@8Kw&&ZXjHb{D zGYFdVE8EbXUkp_!a9+tj;v}%Gynac&B??|P%8S)8%f%-)6h?Jyx01Rk7va+9)Mv^; zcX4a*Q&!eZrHOKNXXG(&tYL#F;41LViv0oX){ZYkAu5(`?aEAxnG#c0!grs)h9&M} zs-CDDF(`&$g^R|m-9V#!z+H(E8r<4oMr%P_`Kxc$hao%)~)cj`HV30 zw$F!Z##NdY$r394O#L{p-M;Cw9*E|!@scVI^<|rMtEFfbltmV_P!L)~&yYU*+nijp z(9u{LF3wmbgDKmV=mS90O5{{oA#mgKQC8&5=-cjAE=jwL8|=C-y%Z*!V5e|RNwA#L z8H%k$946V3s)|n@+sP`jh1g26KNi_umpSrm*iW8F9ov=>F4Db8GMvds5~W8Yj4}VO zH06I!&;Oq$9skm+qe$ySAE~|&*YR^SCoUO})%rHazo9~GD+8Oo{d6K;7FJ9@MEDuv zUM$Dz4DgLLarPg;%OkNKiEOfDD}Q^zJ2L}`zW&-i=Yc0c3jltzI{151N1-L;b(XLO zJ;gq0$(6VXY(L}8Hg+_0#dR93me`lC5dY`*MXf@CvaN6tskFc18{_}USkw}nT!|Vo zqHai4PE@a-A7yP2g_Flz4t}DN{5Yc?&f)ke1|=Ta%&Vw*Ds;P8SVS46vIWj&?uu;glwkch zb64RAVI&%*LsFQ1e?Xe4sOmB;b!O6Qw5%x_bUDSKK14&Sq=x6Eo>=N~7q7~M%|^8IyAxHTfynOkC~qOtAntGb^udXuRJtxrB$a7~QPe!)-i z&5b6Zs|I2|cR*CuH^%eG-eTV^X3tyi3qqdX+bDtJWwE}5i20Xe@o1{pG?OCoc%n^m20yJ*_#N+|M6bvC! z7?D}|FUU`Moxzltm0U754IR=yB4>R=f_c4Na~w-L?E)k%XW6fV8;ZOP{s8dVsUBwu zDiBm3JfHtG?|rt1b20kiEw$GDc8wi>h2V9B>bBkPZ5E!#} zCq{4YOGcJ5>&mCc^ivg9P3_#48As%Z&QZB5UBa$uT(4`asLeM=8eN4O_YWPPoXu=m zw6C}|6IPD?wt4%WgC@9ZDgrx(0D+tI3xdOj}24jVR4 zRUzdlz7AheH+>gUOITFs+8Uqv`S>Y03fbtlV)51RP2NB%(U?sX6ne!js+`ZZTM5{! zXkxB?{Yq0)5nZp@`&r-q0kmWt9VI6h3{%@d_BW&mR09uiBWCZJV_q+=TSvu=of7Kg zB{O)?vuXag(dzVG7uX&8)pSqq{QwRYIbdOiuJ~M5c6ZeGYOfUPxyZDeoH07<*NlN4L{gDUytH9pyK2Fc{K9Oq49Tw=6c>p8r z4}>rfbe2`Ofh3{{!9iBm&N;FAQNV+JC*u=mI(NNJqrBeLiU;3g%Pu zQV~Avm|zqEe3(LQ9e8Zl&HKpp+=>b4vLE(VIFMdrIJ!6PKA&=J4<8dLMuF!V*ZeEZ z+?-`e3?cbpb0$s9Go~wd~&2VJ}SrL)hE)1VN+lgQ*==<5; z7}3KNc-poM>mD7_%TO}AaGoMocq4y0j#+6-Reo^KWStwAv2ZoOeTNQ@g}4mfBh1R+ zW8!k>(eDi&__eL&q?kASKKyA+z~@+7Nrsi3H&)oJ^z6<)dw~mWdkpC!o21jT=_%_2 z5w$Y#`<0=T!kfvigdil08gFu^ZGrJLk(<0s%u0B$S+?DFi8rNQYm3!HSdex1;t86ZbxP%p)<_q=BL@< zoz8>^Nb6xNf34^;s3=z22hCl|_DCr&r`9?n=1TvSOvF|V$Ch{r>S}t*oOV5-eOCXC zU+bV3+nFF^z98Qg$c_0J;}%g~&#jONd~>uAwfRs~`qFZJBDc#8vbS>1aGTWp4R4}C zE91^hF8RHpc1_i-1zT%}LE9n8_S1Md0@p><)?0tRBP*;Q`I$cov=7IjF7sN8Ol~C% zEgqDE=5f-ZD0-8xK>5bPC#w-N$vQ4-b};yzC}F{l%&Wim>HiJV|7Utf;sPW&23QtB zvmm)oz%$|^tIvB)+N=g}y(Z*v_aTqyKJ7I zozoT*iH2Nssl>`Ebx$bz5FSnMh9W=59~4PUoGANYh`tGhe(qkj^XR#I8_tB12mjOL z+R$8P@HkHcXT zM-}Y)aqdKkw$1j<@@xPYalAsG#uFD8pQ*n+6v}m)45Ns6;db;%I_jQ2>WULv4p@eF%bD*pV2k^{s(~P5VvQ5+yzDS@d>x3a~n^)6z1(_B1hyrhQMy5 zvuEudXrjOV$D5-nXwUEcD7%b1odq483UgTEI$u)sR{UMbkMv0aIN5EasZ z>PIAwB2TqsR$_o@!Rjn4u`;ZKeg%eJ(nEERURjVm(BGc^AW3i#vE$iJDCox|SL6JCi2e|A=jy=ATf#bz(h0oV6QyyNbc7w{Bs`YOW- z;q@EpfbgeoJu78p;J)=~61HhVvsmQ#6~s@`x>Bf^veaWKOPp=`5YSZ6AE|ygw8OZ> zH~ocJ!_p{zy(IL|dnUIC&KoagD*0uj$%2EElN5ZPWTf1qirT*qb%MisGQj}3h#r0E zjbxg>M9h6CB-Zfrg>q!dka1_%K{h@Uy>54a{8PGT?%4rGX9*v!?{r$W#5bDj>un`c zSZ}D8d(Y@|A1DX(OWPg#zcF=t*DPKM0inyMhK6gKMP%YTVP6M_qnGY~T z?1>M9J;^a79$XD0IYFK2f~DWrSP2K|qgdMwHzhxhz7t)u3y^oUV0(LtF4>OTiPt2= z9T$ldlZWLL=#ccnir(2v{laIg4W}@cK@%R@@Qckl>h-bGrxQ|exW-}hbXhjc)W?J5dDizHyk!BCKWDTm{wB>VTvPFzRElQ% zUC2a57Re(w7pV2@PK%dXZm5|PAK!pBZY>whQS|rk!|a!p?7x|rPwDmX6h+EUQt_BW zUh;xV3W>KFevC+N2l}5RaSt-kQ!Dk?A#9dTc|y^C!6BKMF1KtYsl05T+DGfoUa0Gx z;PgO6KY>`z3>33$zoC4%X^8pK;o8LE;?ntI4n{$vWBr^P?Z(?Nw6CzCyy(}9OxeMB zvpkX2i&Y;Q+uhKe6o;n#6P8zEUvt8J2ijanCfweastbcOicDB(Gs_GpaoVWA_$+cK zPiQ^NoBn#oE2*)Ob(aWpjKS7HGrFWg&;udRTa7#l3z`2NzfKd%^FF zN1Ox3DXPp@D}{zRNZ|2m;Fr`I5}j!7iqVMo3nS`h>RM`b&)Kg%W9nE~RGj@WcDc~rrl z)vg9V8LMxvPu3dI-va{t;jS(&&X;}qjX?AKq zheTfJk4Q7OeN}w{wcL5x9>&&mor$d|LwcI4l?e-^`xc|rg7nzaWk>( z%JlBUXQ3E%2@Uf2#vy8~UStdA0(qTDC^UR`tDRY+R32quIs84RH>(%Hd&hf58LBL??W%QA`C6zT=w`jMerV*Ie9Oj@L@uIy;c#V zU1$WQH-4SRpSiRJbK;L%E6j?F?GA9)8x1v#>UVL2E)*bee!Y8FHO2I6k_fCkE|f5o zbmJZHd$~izBHLTI`614ZTHFg!WN@Y6Bu?kOW-{|O;+Br_`#Mu$$!9BnX(d-*Xh4p)VfOdBd=sGadrUeCEN&C6=R`|(CII!FWi7eI>lmgV*aqxv4pbji%gAa9C7nmZr7#REOY&eShG z1?~mM^6f)u{%v9&EoG9BG6VWq%>9HDqt~i6UwM)f7aR1A1vK4~k=BJdZ#-}3M%jW( zli#kc4Ml%pb*f+!=x1%Ef(C#3j}0H}DH`a`go5kLzb#h(Z>yAlsV)A;L+Vy3j~5B8 z1ALt*yFo*5FCKa|hdm_PcndpLK;AY$)Mx5iU%vS(RqhFI=`w+I%#LLLcq!*fjbOop;QNpUC49_Ir=lT4V}JsD=_By;l=U_8uYpH6tSKFDXKRS_kC(i7FG zU|(@n7h{yg-?GsMlhu)LnWeo*^BoWi<42Cs)p{JIc~Wc?EB}?- z;>RYHnBYyWaYmb6EfyVp&7+axp9<2NkKPA{Nnrhia+?dMDEqW}S&*?XJ>xEH z?k;lAVz^T5et#-Rm!Si1AgNQDOV=gJHJXSnF`P7$xYUiGVc~YEam8TFiT)Eg<<@#A z{?)dWZ*=XJ%q78&JN?hwkP~U6eJb29@?XQbf!mUO6sc_T&924_|7oy znHpusajt`l6d75C_d(vZ>Rm2UqT61w*f~FJ-l`Ei@YOo^AA4`dT(cWdz zEJZ{r;mQj94gxe;7ue`++6n7#mVnMCe$#;2Ixo0nne| zMihtm^pssjv^=lx0~~f)m9d%n^_T|%jn~lkL?k3Hr_Nl$ z`A1wz6o_KlJe7V9M)9;n!Jc1EyiEMKGz=Xi%+}Cq?b%@k3X=hRGLIr%hocY|k;9B! zin~{(iO1uLZZJAKgC8LG{<2;ep$?GYc5zyUkwlT`_)sb=Lhz^rkE@Od)0K-ble0>i zFrn_*E}59q%6dm2XHx=l`nE{;qUHw8`+2!wWmw`=vDC_fX7_{9iyq-Z#2BTTW!DAa^>^aRZFbXhHPnP^!@C0ooG^y z%_5t^=cM3|_k$xyrv|h8Nu%==`K>KOUyC{KQOm(CQaJo4^^V0XX@1I+mpcS$-J0Y8 zLPZtiFkMzJDTzNxb9%aiD{458^ZZ?OqXeC#XjB2)Nb|;Q>D?mnAAl>r5kaR@P2(O` z!K#z)sUI4)OKufNb02V$gfvJ~rr#o@&|DGu^7gDDf>Nf|u<)Cvb&gZ~VY)3lC+lFk zI+wKYisa$SBFRFXEDkHV2(XGWyn;Ww#BuAD`|b+UYqmkYaaPueJJiSvNP#w~EB`E9 zcKgNq_C5PT>NFBXCTX?+X;5-yp}iIJ(2Sy(cEM+rPb!=1%eCj z(hoR`Fn2X2g39)%7H&Tc8@_G&;t-kea(!R?d?7P?%f$Ekv1wfJoa?n~2|{*`({@~@Ins(v1w7unectzL%m>HzZjj8FfZL4C z-r%zFfEB!f8p0T}wuv|r?$fsw2CI*z2j%Z)ATqJvcZROWHhyT#_=heTE8<*C zoo}*;jE-U|NvY*z+Y%EVVBE(m{{c{5c%*3^8<;lJIha5BD*bd}1PA7#wDZV(rf^wN z%?3LkdQYYc>zqWI(C=$#^19f^7&NhK7KU5paWf~M*UrdnZ15xGr+uwwb;liC9Qi#| zgpYJ~jKC7AHnvzpt1%V!b=Ho!3@R-{FAUPbSO(5$)J~9++DTW)-S$zwL9|qBP0NQf zOxG`|WI@R*uM(YK-kbaT`j^`x1szhrdr3D6nHlar`g27biE2pF-2&gpwgaUtV**2F z)=^G_>EB`gzb7Yjp~>YS)R0-pf&UE}Aoj12!2g(G|Mh|=1%y9N25GyO2Yy<;A zuw*ENKgXm5{GSP(56*%@fg11M`40*KiAqVdDP`Li0DGoT4!4lX)|Q%i-V}jXK->9PUTO9R zyQ%&ierNNuS;08Gn_=e}T_#J}gb{=x_fJU!V=UJ@5` z9_BaJT6@pToJ@JOa$?A(c4*}StoXz=vwYx@=+L0`YF>5mv@@`x`=R8F3#|Vl(hkn zDoSFL-X3Sly&Fb~XnZc;?G)zKXvkAe>`IScs2`+F%*HhQ2XS*Q4M>u&^NEINkgL?s5^gcCz9 ztJTJps0XRF7FUE1x_q{_MYmqXQZyi93^R{`xrKws&SZaQSth?(ZDPmOY8D3t-dzxRNOY%bh4e^J0srr z`&T|25*a{O7eu+BZklVT7ANG}Y!^n2qQvU5@mGcBl=5oa9Xhvcu$*CvFau69FS@Ug zRLcZ%c?D+v@3U}^lAfYeh1b1s)tG_8VRGI&LWLSbrt z*>bc@rNXs#nog}Lj07bfPbLSn8=dJ9)nqQFU`-{|%kD6+Nb(GKL`ExbeB?p&5>=qE zUYQ;)3u1B&^)XZbnceFqxFf=(Iv`v0B`L9pItVue_42-)S55C_9dW|AxbJj1;s+t^ z1_IEuJcs=e*bSxKOa1KD-F>oATK;rjij@)+jvp~UM1(T(MfZQ>q%MS(J^cDXQ=q5br0n*)z#p7K4)>dX-)<%u>EJl zC$53UArCs-Qo1r$GN_2~L}2H`(MnSyjaeMjhav8a#z3#6qdl|u5iAYPjAATgWs{-U zG;AG^z-51d?GhVxo@oAl1y$YlDC!3=vQY5$x2)b0XO5HFe1_J?ctdl8!)(Cnv;fvD zblZsBD<~yCvjs@SBl;*?M!8-{E!7h&4nXjxz*nX{^R*Uv765k%k+a)z+a)he7qcqza9fCKK zQ_G@Se9_*XHdWLn+k?C)RKLN1NB42&;p4VQ1ED!(^^pN3o5I>3rzf|q7w8$&@L1-7xBs5gCXqYgP4Z-2RXuTuBU{?>^lv=Hehqu3y~sGm(Z zp%dKIo>xNc)7@xZ`Bmyiw?1??TJ>^yFCfXq-?0smf|!65Q4Lozr**}cec~E>pA7L7 zsrFbA0@D8zL&okfqVvrtF197*1h3cix^pPC(BmY@ z@c$1${_l5qx<`yLm2IMioQI_&Ern2#d~;-)_-EQegNQDh2`^c&LEjL!07v|7C4ymp zsXhGj0^}jKx6IH{^j~LuKr``mL%0ek%tgo^Q3Ieffy;+PqZ!FAv3*qG`o4ceg?hGO*;(|_-9PK~J2G^0It0J}T*$8aN_uO_CaV+i zm+6ebQRsqF7M^vdb?j>cqF2LS4q$L}0{L8N;cXcP^kTWiDvs&JwW6Dg9QTO@nV`Q@ z;ZkBT!ymvW(_9Av<(;=`Na}fZyP1TZ^36)OxJ%u^ymWzzdG} z9z>>Hh_%WdzRXHL8<~2mfIibOzg?!lz?;$^f=6%6S(~2VtwK;2Z(5sap8ZTQ7~G&^ z6*!+!mzqu*yh|hjuLi z7I;7S3Pi589kiYkhY7u67>xSxh6?E{)P~$d*`HXt5cqAURx*<+B6zSh))LbqYuK|& zF!iXdD_m0;kGNBqgF|i6h6VR;W5rig*Vvz(^_s(VXOBWQ93Sk`wrp=MtaG-^{%1K|DH?de#Hf>s*ZT9*> z%E2Zhs#3IgLKOQ$mo)ut`gW3ffra(Aqqf>*IXfte>ldEx`@`frhJH}jpg|FL}4WGxjq= zlVeb<0$>4>sK|of34-DnOuirgZ4mbNV1|+uSI%|De_uf%#Hy-SB$~Pr6b>PW_FaIJ zGKpr-sY3u}$WUg5QH6|td&E!9zZUTrx5{|%_ z9wD0@o&LBFuQ+aa{s7G1{BCOIJe3y}TB0tY#Vbz~TMUfa939buCK_rV7Zwdf#5lho z##s36_vY7L5`9K$H4FAYwd272c8R(K-JNIX((}Yv`CsR;rqRfT)?Lc*eSQCA+)Y*@ zawi%`KOSN;2M-4qCvGAa04jg0`9xOe8gOJ8N4mey|1X*1KOe1ftb|;Hb|E1{o|1?+ zzKN)k#XF+96iH#8?M~yYg<=_1E35aX9P3WGr0O~60VVq!*{8x`K33TGw#%Y&AEl^X z&H_1$PYGYnX%c-H6|<7Qa&|&8nbE*+Yb_pWe$uB3a_>-S<~{Ozz3Y=BkJ0$*KseVG$tNaQjF_pHX5NEElR zX0*|Y&2AY~`&hg@jrQyOWz;kN;-qMMA`Kk*Dkp+G5rHqOu5BTqC)qH!%8+2;L4jo6 z;*$zY5NQz$%Qnm2AArEIsm|jdKk}znp;9@*(y*BA>PC&n@vO94LQ34;`1iHydz_~U zk*igqh!-Ry*PK_V8vXzxiw&_fZT zwLS!^tm^B0AK!s5;t{BMCnk%GCG7`((cep~9!<1^SB4N^%1^wsC=zpZVbqh7gJ?SC z+qXB_We^A9k1^*}(VwAr%g~rTupl0yykgt2yo zMFf=^2I!Zv46qC7(X%MH2^Z2c?O<+B=Kb&ee&FJ%~*XjySkg)xRYJnHl-zPYkF zWj{j*!kXJsI46|6j$hZJ=NC!531`H;a!r0@IO=rbFCI5Fh;TmEm`O?AYt`xYKQ!Hv zcXX+*;om7NZOiEGbb@}&Im4L{$O@K?q{sCnxRly2Fk&4LRWN+lfE`P7@cgaTJ1NN{ zmebC!uE%PEG^*EERYXZR3<^$MD<_Wch2tEz#Te=PogHSGeU^nc><9D+XI^PFF$kjI z7ZZ8VFGQz91~ofPH^$%*-Y*%n_>yffgDN0ylg{ zj;A01TwH~}P!a$btVA0uNIUhPao}I;$p4dPZ;7Sp9UhQ!vVhDW9(1wWDJ;O>s%VV4 z!ZK-;M4NAtZhwoYNW=t2{(3Z$qexzc>O=XNZoqIe1YCg+v6QPzhRjCUCj@I$n)^VC z7gdPoK%bahY%xs!*I)nYSGoV!CbQ3%J4#CTVJL|I415@Kl_h!oAO`|qDu-c~c{B?G z9;*|*6T`=i2N4}6*Q{>w=A^7Yn`LTKj`GZ6XXSNxVUyB4__(b&wY3|lnCZJB=p?#IU>h^U)hy@4JOyZr_{KoDP1QpcDBArkdey*kD*wfEPT_n|4_m)M z{j>JdXHJ|)M#B-mmPcj=1ocibDP!(tzR*tCP;*YU4GZ3lx7q_uaIG?iWsp)`i~PxU z)7?_F20^I$&?qHiu5|a^*(1q!l?+h3J| z66;2IToVjVcrXvG}Q{UfmD-*srRenQp?qTP+m6D4#p~Z08y4 zkB0IoscgmDYE0JOvn(Im?SLh7N!k4SC4&Zj#u$#k`*^MwX_bN+ya})8o`xKvR1EN@ zDa|)&J{MsP=*x3D z>SyBhh`60-oeFAUkK+=N(ISPcHoM^@N~ruLZeSn2Gv1D3nqqF9NB~0O)#HN710Z%)^giz($~qlyqg&#Qp+92%A|4MVSC zV@Hu}nwJ6uAhvi`?Vx{FNB;?q{$FXDQDV+9FZxlAZvqIR;|MFii+;7zm~1voVzf7% zBVRMNWp+jO=*J{K<`N&u9OQ?#1S3EzPhATtI@9*onxVSJN^ zB|_^#p5F+kLY7JlSWg;2W;@xqj22tL%ZVP;t+_17sHFy!_{Wpb_;r++jb}Ge)T-Z(Scjo~;8g|vMHRJ*o|KR#F?TE_*Le zHzm2Qb*rP^>vT0T{v!1c0HWGl(#0mM?DF-yEu`B!@Y4(QRX1Wm&Lmutq`n1qh7a5h#IEk`7&KX*7)p zLfN)8n|(MK^aTpwO`kpg06u3UT;fZIlqR8L3M`r2){e2h2xb%k%bN7oX0#7(!<0YR zS>LUR`ByYkTg!m=2Q=*GJe|U+Ownb4!3>0fkK|Zy?|(~IfBXG*nfGQpCZXpKAe_@N zqfifT$Y&fA3rqZP!t)sA$guSn!Va`lNylwvy+kY9IABwPwGki0dl)nl(TGE%<{O%NVPO1CrdFbDc}y{48OG@pm)X&ma*=`k+8wwqcJ) zl^S9<(kxJylUA?6r^6J(Gm_uT0_D94w|w3vo$(Yu`W?gJzamssTWac*4a=n53GOSj zx0LTEqSxII^eTUBkR^hWIXyh+V@DDXTrbET-2=lZeLZw{G7es@fc=z@*e7{Od|lWT z{{S5Eaqz~RZs*SXsS}Jv7*_=TpU#dwp2_|FZgcNfbE}Aq5Yy=<$t`oYtrIpYOr=6G zDIB`UWhB=ybEy!Muo0)Cw2pH`H*^ltD6LXU(z-F@G}qrda!u!)`tSX`m*@L@pXd2L z&+~ns@AEvRP0m>6YP&iLKc@cK!He`H? zXV%x36R0Mwn8^*(H#LNaG^D1c+w1G+2nX89NclEm%k88WT2p=4&nW`rAk( z%Ol-3qxRJw*|O|7q`JDgJD!j?@f}RKRh_l_TXAGd#Njc-C7)G{F@>MHOf6{dnY25x6kH4$l+(6QE}Uq4nO-jC~f~3&?rS8&0WgS z4GSr$K(81+eAC&dE3lU8uxc7aYcUIlYPhI8vRaF zE{5xr^rB>~Pp1mvGTmPl#ej)2-t6pf8fd**imPSa`d5TA-1t{cB`0lG=+*o!w5Dnd zI9rkX4mYAv&9xc>91*vEa_VJVXb?nsM-3iT2R|#~gL_>Doa_GC(_=W`t=PTH4u2eY zaKcVc>t&H9KlB`I$$f}v=^cYIPda@tb)q~m*jkKB zm6baw>aqVIYkuc zt8}|M>({?{D;?>AwE)9AW`Y?}=}C9xzi#IMN`Sr|klhSj=LMeXB3V$$X#tdV`PqHS z{R6b|l)0%Wx=xucJL%zVT3)RgWH;TN6@&2z&|wgOsfkJ&Mr=}CG1y{G$VImzS~EXr}umirNVkh_e3@(A0ukVreq__A!^ zjJrofl1Y)+p2Fe|wY7R_tM};GEjJ?`5eYO_`MtZfShaHURd6gF)55kcqPeevl3eD= zpi7Q39?hLPAa_qV7JXxZ;*bhC=#M7!%8XyABEz?73|lDEgA{!Mk7^W*GBoO zv%B1UYdkHjLLmZ*<7R)#=>Gt+k~mDA1_C!1gwk&C56F~c4a#CM0L3U5J5w)y3$<^H z_|Tsg*k3Lij*bCFARx91A4>KG_oVqUyV3}XzIJIEr91KsU<^G`qp6X>=U`W%PW#BE zjfUk(KOgF+4`4VKBJ=IVvUNJKH6j6Yk8Q-ORz=oEm%*A?(Xk064E0@N>FU>%s7~ZD zC4@OxqWrkxw)Zh%@e2;6Xq(iV+%ga^YKzJtO?f&yU7y5q&&hVUN=j&oN_2HO75yz} zjtNU3j(4gwWmq3=)K_@C7wlHrAUzM$7cYpd94yGdx}= z?~MVNtMYnkv`{S5&JW&}M-`S$ou=^Y%NBBwkctbFO9A6t>=ZF(yrjYs3NNfh$uavW zL+7=k0eA=&lxJz%o%HYL%M7>c+^TwSayBw z>PKw3)Z8Nmse&_=QYgtdQ?` z9@>MJ3*sdgPV4rw1gR&?+-(UQ+SnssqO4&s-q@X95QRXXl4*DwvX!c_i&C zRA<5g#bt6Xo0rsitvw)@^c(BZ75GMxco=tys{=kb@$O82i40_-9iTv zwAUyu6p?2p>)OZ%h?jNP6D`w26YeLDY+1%MpG{~;zpC`b5|M?`My!c`5JHV9SD&2| z!oT}?a9-oOSUMwNO?s(!pnD3^Ol=p_kj+Dp$p2(3<}&vi6q`Z3@4SShMzoP-PMnxM zH$YxIuK{W&70ZQVVGm`VWqgXhj}7vWt0QA>DxxT2759>kdEQ%AIV}C`u%pPSWMYw3 zJQo=6CZ%!@=xHw(;tg|uXJ$O) zfFMwel;dSv5!&Yc$_19$l$_6spgIAE0WdfKig^rqPDW~KL`tadg_B@hWxOGi;P~e{ zzufRVSn?%2*bkAv`0Y`ZutN{8R6W*tQd;r=Q?u1^{lV)+ z*{%tO#5kM**Pi$yJG=Asn)YAn6pMlRXb2cJ3%3+fpmlqs>ACt8{ePU|&ir=drU!Nx z&4gmeek#g|j(gdk>*m^@lXPg?iV-h@!J2gWGNo6VtFRFwiw;`m5;R_Ln7mp?fBzt> ze21K?&EsE!aS<`EueAI?ov$6hO^Y64fc;ZGq~Jy(I2XQX44C3m%I2?`w`@K}Tn~G; zQV-p7&J(@Yep6KWgODO|gr(!wRVyYG!<^-@DDBHHgF$&bjRyA7#O;bJf2nCj4Y0?P PX8Hcp>S-JVY^?qN=zDMS literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/assets/jupiter.jpg b/lib/layout/imageview/samples/assets/jupiter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..23376edeffdb1eb266041b62b351ebe395c4a40d GIT binary patch literal 27149 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

    lOFFHf*4gLWv||4EUJns(_; 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 z z9+*=%=M71pa8ZRq4YIe2^?Bz)6-RvIST8gVlGEm*vGNA>cx-$y!yUknfB-ca?RDV@ zaNc|c@(=6&(ffksrJJ|+a0(o+KKlE5AhdEIZN_bS;FTe7$NSY#b8W#v$v2H{;~PQr zRdN_aUyMX;@_D9~FVnF>B&KP6OVyWUVUw>!d~4Ibfr-*q-> z#8izTb$|9U8k7cBQiU??h$Q7i(#HHA&br9@G2L$TgNf?$EDy8I{h7Ax3EQ3ucloLG zn`O5{c}FIW`e^n=G_rijoOr$MhCXj|+jrjX3FlWBV=NR?v1Zc}^b)#1BU1CuUA&#Y z>Mc6vxUUQgcCeQRPhQL&xABWpT2c-Vt%q7JK(1aF^DJbJxo&o=soP^Eptax#;moc7 z5M#s-Pds~Ca1X-LM}wXTC@usujI@Djf_Cg6iX7Vmo@`0Xyd&6Gm7iGsN#Ehe!*)sg zz9MMe;>3zc)kp5+8_;3HiEyO_lIN}2+%d#xyLcTpSB?Zt*n8QXeW{Lal&1ZX-Ozf3 z*4H_v2&G!0O9hA8&DtZ;tej+t>eE%WO--ss=dTo3}n{TF4=W;r!gw8W=S`swb_^t)p07a(X%uw;}g6TTq zLwzn3)cLm!E%*og41y*w2IezP00Y$T1yLf>>Iy8kY7p8=;u4~>=wj^%u_D-=VxwYT zM%0%lmULf}@ZwyInJUFA;w(3}egrv_ql?Xd2XBj;6h|}2Y_#qT@rRh{i;3z8*C5(f z<}*q43NPCGU1x1yWW0`bH+NDUwovl*9PW+32($0xx+x)87k0xet8VD`i)dfE5&nVo z-QCUN)hX6^KeB70OVupACjn&GeV!Te zKKHyMK2y}trS-(116z_DubYePgw8y1w)-aWyFZ{W%zWy=iVi)`GJfc2+`}ca3s=n_ zyd&0~?{KiZkAne=y%n;RD&~ZVe$^I~yT>gz^Q5eW(Z?2-lOdzq!T)T2;hYO1HtJI!`Ch=|vQsb#{ zzblPZa$bLPGQ#tBOG~Jt?Lg}k*(9O#L_+97fXdiZ!3;XKKvO^ujyFNSFyg0ET{Tct z5MVn|q!r+pBh=%cMGJ#EFRCq`jdHSG@j9N**XD+7<|UznZl{vC9rA30(W{y$8wLtlG_Uj zW@$UIvfB-UENR37`_a>@-wI1P{0`6(#B&{-wYLJxpo)uFEkkT}YDU3{blF|;jHqYr zPp7VE0we!3z2PV+&dhyUNKd}#C70@o$yJZ32hqNlx-SW!(}8NH`^#?Y2@!X$U9*zd zlVWbVYP~4U)KzuSQjY$y7J1pWS=%vG&JuB4iN5hy$eIQC^Z0Is;>5BKKKp!T+`OQM zc`3l-EG}L0(WX`OT|=g2_X~8X@djI>5j6H2nZYu=7OD;NnBSwH&bv-;YsOg)X1}0= zm6ety^ozJ*7X3)EzUqF#N2Q1+GZ$r$nE)H3G(@DKwWvvP{p7dAVu|#3Ky38fmhr1g zS4cnUQ%3-xh2pmHPKSW%HE9uPd{$G5w)g6 zzZ?{#AjGUE`l2+<9WMXMy)&UXdeho`&sTpsQ1tSl!wbu-cI25~L$nB#mIPVxZ^|?Z zxT*aaAXA(TPbsh;#!XHrEO3OE11k_r<}FTHsOs+q z3H$nV2`SPS>rg20G#EM@p>sRDhW)Jb(WeEu)HVsL;zjB}CcA~*x~CeeKO3~@e=B#e zV-?v>!o4=ddcHwc`kYt36Z%k3}xg}YOrMfQ?2FoSPXHP417VUfS z=a>c?wq)rjJqYigdtvwTc6KAEPoLP3tbigIwzY1sYTRmXu#G!6f@UB*FlQxpDck!8 zlr}4fiMu&py76vmF(Ue{#8yb{cA&99J>3^`2y}SV8ebvX)cxv6@1Q3}ejr@#h~MUT z;OZ7e1mf^`s12-j1LxH1sm1Vtt(T73YoSoGC-^L?ODt`e`-VN-rB@JpH_nVxG+Uuq zH!GxIV;>N`ePh4O4J4 zfqJ8jH&aAej4H9T*1Gg-R_Qip>5-9FXA3V6 zV^tT7O$lTLnQ}l{6t4RqSR;;xbAWvIr)5$q*kL#%j_z}qpszcSG<(aO)uo`ni$b8k zs&?3Jh>yl9Da`<_GT&YXxDQg?_9IizzANCcwgIP;-yn{Zz>js&hgH;>M%SP#O&NAi z4it8!I8w@*ALl|OxC1s&z@th&G+rY9?8IN49lK=?0qqr+!ryyQhjvH6Th+H~-OCz2 zd9_0M47+JnZvq~A51O}K$BymAZ`Y_&8cp#k0TFg)e)9g2VXH8Z?4sY$Z5~!Yub^pj zsJoxYyM99V)SCh>({R+DCs|vY5v8+7c$!EiHer{f6A{qd*E-Mv)k8#G-TE1J4v@{J z3bJ0xaUB`?w$y#)FuMIlkp9Yy59D{{l3#DT3(gMwJ&lo`3oI(pH^k_t7zOYw{Gt$r zxhc&nNFtlhRf+bv%_-L7i+2&lKXN2AY(d>kczxPexvBJ(EIayBJ(853w zhB^VOsrOjMG>rQStj1n+on+_WP+ui*5x7BDNQE#%5pI0INPDdhlHuQe=)ZF6?z;4&2b_N@ zdVL>yB-?-8Tg%Zy66|7<6?TFaiY1|gs8Edc+a2{P$Q|~ z#&wz!Gs4c`_g5!;HEx{7XQu;-V0NV3B_O9M3`l1FM&n9Z%k`9{+WYp5IQN6>mA$(Y^&mKKDXjc!PV%*TVnVs45xXkR7f;=662#%8Ei z&t>TfN-O!^Z31=w4@1mo|D{uRReuMY^M9wI!1_W&t|JTz+LYS4FBk-^R-uLfmJAev*x=3nVKqBRxZFcBY=!AAV#63@MbcB_& zl1raY0mr=u?|I;<0XT9-7)MET*w@cwy*S+O9yi6Ds^_L2$#&8kTcfk^;vh}UwsKhM z+&HLG_2M98-wgXk7{841MviGsjW*r%Y8hVLwbN(n_2A(8r>xX814 zNb~@jcR|ggtAQlU&ddR}@Ppu&C~}Wt(wnmJqKMgdOWY5R_wQYyKYO$gIn|&lq4d+H zgikCwh+Y{{S~3FmfrzZfMEMO;!W8g|6xIcRMf74^$l$)5OkqSP8om!yGiqa>qTCM zjx;C)|I6SWK-*w4KxdUnMfVAa$iw330IC6sCmqYtLYttWgNpc5al%Qp#=IEb zCXsF6^Sr4|;>b@-tU0Ss%qciQpN+>#L$~DBLY_9i9*btdn!o4{BnzyO_EoFV!-R=b zjt7l_BubnDb49y$lGqOQl_)#&$qI+aV`{L)-E;}g^D3PH<1oya(KIrh>rjBjN<1K3JRNlOHVJjwq||vydxgiuI4|UsQ+jZ z{~wRp_z;%ILUkGZavXp^yOo=zp~CKzTXs-Ox{8o2g$XXCb(%qi8A!bkYndwDHmDpd z2Op9Ge<14x4_Sy5h4$b>0EM8_P*-o9t_xM`-#sOcnXrV&7!{6uk&XW}wr1`Lg?A;i zm`jQ932+TnTYXo+k+I&IdOkkGybUWEY?)QjWh=r7UQ>u2KbP|kg_ zNtNyB2*!%Ta>Xtu=m{Hz@gtl0JF-y3O&|~5pEbzA)cVjim_QoT{L`^sC<-7q)wZ?( zbKFEHxXHL_h#u71^QQVwcH^xMrodT(%-F@Lw0E!Q%~`E}5We~KxH*?z==$ovVC$=L zd=!@OR7~#R0yz7*`29vcMM+)z*MDJglMRKPPB)^IdA56Q1nX^xkLq;i6haFKU^Li_ z1$brF<0x(M$&@4E$FGo}_3l~U(V(3X;b|5$;im11BIsg@=HANh(ThNnm{achkl@ly zi6?4wuQ1k5=BAj^7&2McGQR5k;em6necCmdnJ+U8%NwZuu;kRI?`|SVfc}qInMVtse#uCap~ov!oz~b0mgsYE*|C$#ykU7$E*|yt1O4{O zz?0=ErWthxE-Xyi0=<9kG)2icwk-Zz(GY|Xs&~Cq zuk*F3=4Z6J*-XMIXt)qWO9;BV84?d6&H*n8NkJ#ogTkP8`>{cS>|i>y(2d6Hgn>Vd zRa_;X2DRhV{#zvChP^3hq&C45Fc1&Y!C8$^8lvm?RiIdka&TTAma;Nn6Q$2UJjTN96|QkBx3ifno}cV? zx#)a_Uaq8DJG3(JAzbFj)+}uRnO8r3?YjB(s)Zt8i~ln>0QtY%1CtJ#5Q?gWTIrM% z{f3a>kg%7#JmeiQ<&NCJ2nnl$0>J|`X6H`w(-2mOV11>g+7XV{(xI|0d6pTTb}R8WXkSD^|p z0bvG9sv*9b&|ry`%9kLoa0#3{=@vWkn{ub%_#3mb@l1G(GJh@p;D7cyLVS#{fu7Jb zm0^I~2~y3U6&FPz3fjSjH$Srk!HG5sxIF0f08oR}zSlDW`0~DVYQ29$RB8dA&;-=; zff0&U&%}>)(STbJ4;&bv)IL-1&ySm;6CjNN=>?U?IHw?qlxXh?Fo1dhMB;*U6o8Js z_(`glf5XTWKXEe?wpobtl(|0x02Jq$XxfIrVT$G8sGt^Yhxl5l3yaa8$ zGq%maY7{%KzCumT4EaUZfBAx-{kwVzy$0ZffRN3oyq4?(rZp!j6Pgw;bOaIFfZ**w^=_U?02oY$1KQ}t2pYfY{X&I1{Mm?ao3BRVOc0*b}O6+Lql!2 zjpRsBWyGav$a%Y`nkcTbkDIxE^M~;xn7pT}%~^O*(~I5RvF;h1-nz zPg^?Mivqxvn$&ev^h(n|4q_=lLr8KV<`RR5>bSu5bR4l3NVqZKM|ck|Qi$?XS8Egt z=Vy^+`E278E$ll|AD5MPVrRm|AS}dZlXUM;_gA8@`mh2iPHZr+u%KA4A$^ZXfzvij`!nyIo(~n$wC*A-6 literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/assets/mars.jpg b/lib/layout/imageview/samples/assets/mars.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f192d7a0783bbc642c6ae22a6e7f73bba6e6e5d3 GIT binary patch literal 116236 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 LCjUoX^zi=!5b`-3 literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/assets/mercury.jpg b/lib/layout/imageview/samples/assets/mercury.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9dc766ee464237308679ab9f55859ea7e44e927 GIT binary patch literal 206369 zcmeFYcTiK&*EV{9kWi!}U25n7r1uh#-U1?m^eRY4=}1Wc=@2?15S6Ba^eVj<(SS$| zH9simbn!j2DXbp7qbpRq_ z0C2rNfU6yV?oN=4R~SG9fB*o{xo+A6sNt@D&TfEf?{y2&)e;Z~fJpu$*JltIbp3;n zfc$Pa{|Mv%6e18QDH()}hJu2Ik(!$Nf42WW zzPRcI=*U3VV1BmH}Na%>J27$EeVH1-OUCZ@I|4#vt5|e<5AY|nKx3>TB7cD?c zbUh1V5Qqd!N2A8Lv}7tQ4A$5&W`V^LL-Q^i9ar`o1$X5J~n* zE9VupiRnn_0CnIp8Y{#|K}sB}fkFKL z7ythv{C|5Vps?kM_dxaYRK}o>(R74^+J)gjpljZr>4d3y3nqC5c!qh$h%Kg~Bb4Ve zdf6zAqL0obH>?{PokvnH2H$v5$+nA#)z*-9%bx|{cZ$#7RNfst<`HJ=sOy@M>N&>R zyIcV+r7f?L?4OJm#Ur1Al!LXTT? zYdz8DJ_e_wrUlT?ABI?)p)=8ohUe^+F;-=~L(i>Q9M&iix+zEMJI)biCqg(>5ML2P z^o1$B!E|1|iE^Ry2B`)|TXiCw&xiW5iSF~+y)$_pXo)(dDW*CjE|HY&qMWwmUU3Po!R*n;+Fsa4en*r820iHFV#YWR z0lJneKxh`(?RTl-iX7%r=zg1#>i1W5>YS9+V)Z=gVv*&tNSRn~H+nM6$**^C;0kz) zEET-SxdH+l-DyvnK58@Xxw!WBp63=jTmcoR=LcMk>LH<+k+D$NxrNP&et?_R;i0dJ zDITu-|B`m%+8P^0{CP^w#mP2(o?r?gsL7&C(cY@AwC2;58RoXqX0zD6mr(CH^^9_e z7V7LNA4PJ!7A@{_iC-wN$JX|%+z z&SUQp&we|-AO(%y9U3jmb5l-Pob4WP$S4P$NYy*3%^=7LG{9u-%aijeXoYSD=TGZT zy@NGf7c>SpR>c3&#}HG38yLCfvEC_%KX=xn1a`!I{jPvAgi*%md)SNdCLK#MA40k=XU~b+&xHg>pcF4$buEY|-Dj@=z}tiO;pM{b?m*i1w$OiQ)xx{tWZ%B{ zYdD&k8c^RKi>@!NS1D@jNlM{#XQE0yz?1eM5;ZSH;e-E7FC|Zodrt4?kB;zJN)H!` zs4T;!)Ej$(qE;j>8`lqh z<5L$ZLkk9?8*?19kksdMc zvTD#9k^dlPqe<)e36F-P50j-Sv@_eueA#w_d(xkLWzvH!{c(x70*;#K&vwu;Z{KzZ z$<azH9leX3h4R}cR+F;z1k|CE@I zp|u7giJ#H?viaV|)#alFexHLE0f6}bx(U{hW`U!~$(?7_AJcn_5BEk2!6eJ`BysWB zdN3ijiZfw`-eL4(ADaoKQyW0l5s#TyNwlztx6*$~$m_@3(F)<2KYhqQCVIBNMGwUYVR|k2h6;XT;)4%a>{7lQ8pi zvAp+<;_(GSAQ~;l=weWIF>f3nqwAfgRXdt(r)PffoqsI2L5BQq+pm^m%_{PprY}3N z5o$c6HaA0bK=V&HUq7IBnYaR)uYkIq#|)R1>jBU_o%1ogR$7+ck7=#G&l^!PT*?=p zuYe&x&`9a-6(FgeUYw+wiYfF*``k1rSdKns!kqltGd+^O=)dUrxVnuWbE$#}^a^Nd z9H#Xvs-Ie5Baa2y1*t=ZCgS%GoK;*C?g{;PN>K+wJo?|{7P6MP6~a}tqRr-M9+1C7 z)|Un9QHJR4zPcE^rAXIy7rTi3#X$7cfNW-zsaumKc89c z9lB+lF{cH8s7B2}?l&W6aa6a_YFJO)dzQqkWIsc<&s)?uAtH|3nN7awILQBOMJKi! zC@m&^h2Q+lcCLJj_oe{Leh+TE%7X>dN{XuF?-a&x#?8}JHG{Vz(B%5rZDDqd3qBFVn0a=Do(Ud= zV9!Ap2VoNc`wQbE%qLi6u8ApY5S6>Y4;1#nDONA(v86PxMq(oT;r$K3>yh>rl;amK z25jf&JX^mdtF$Eqh38=QC*w<`_srwOGAdApSZlZ(ZPEh0CQFP(bL7rN8 z4J2N?^H!d<>(fx7ta6EpA=cf;Oy1`z zl}pOIbJ@@$&tAL>_eqqrrexV<1uchG&918c`h)ps%J$|V;@a@H^o0@ag|scf`@;OTEECRd;F>D+4xCyWI;l_ zK$KX&#|&W|$7Tisal!iae33Md#qR%aE1@0%{G?>L+# zojDbMPFK52CvgR!@wICC)BE%Kt*_Agn16%lPLnBva;WCLsn{FUREgX>+F+Ug_BiVy z+hbq(dL<%feL*Y*IiA>~kYv~qy6+;i(Oa|U9mF1vFiIzlObmFPs4gng>1%C)ekXre z)6K|Ci`UM8A?}p1%EtN(ws`>qelcC3PMG(LPaBR}xLw(bh_kyIxRj?Y^(&``n0y6q zj|WC?`k{`^nbCUFgp{HSq1(Nl(o)I=W}Wk&pGepAr}G|xwt{g%r}MC{{6=G?!uS-C zAUucJqRklWp1CO^PS}S!Ho?aXVw(X&gMGI z06QfcS$U3Ywn}dxH;uOe(OPG%^V7ke3Y-W3kOV;P5bF1+xF!Pq``m*+VeC0H=D>tI zF6~Jhkd0}-b{!tv5M(XbujVzBO<{DZn>{W5d{``W`x&#mm{xF`E^Bv7*HKq|#xN?< zo~2;7^mc~GqTXAZ7?-#EUtE5|gPA#5tk;tY=SyZn5E{I=c6y@jCOUroFy+n+QN^=9 z*z4jwF{kcBwsMbI9@ae`_x2fFIGumU55Gs`QX5g3+U#8ib~OvfOq@$Uzs#a+@P-h` zSjxe?C~;YlXhg!|PdLHMQ1aezQjD@Ra^!@9JfHy?k<831MYeeqGh(g*I&Z=>508bR z4V3+%%a+@RGrMr-IH{vb^teQaWP}$MSA?*^f4*V%diX%pqY@2CFZvZu&XgQRuIL9% zIcjCX_k1z-kQE^Mhk?Iv^1@?_?!b;+E2@G{)qFpiQRko zR#JK2)}T`hHP?Zg9Oi`Um-?k}n2M9Q!%p>VG4ox#O7ic52gi63YOyU6?knIc{I>&6 zy;(ira%Muop{>*PQqA8W{UFK){brrJL$&q-<{`ZG-wBr7I5Qno?W*?fF1rq&%A&ZM z*1oqo6{NWMao>>n_5|Ot6&(+npJN_EK}8aLG>r&yA3R1(-zHPtt?qWjyR7xk-Mf>` zpB_I-@g2>E4BBX^y8@UFZ*{=e&K=@XApH_Qq{k>+l|Nr)j9@3+U?+mHEo?7wj2> zQ5!mUjz4|REcu!a@x{R}THGmp!>@qEB5Y8hbpM7>z$UFGb6n`yt~QbOvjV1jH$Po*MUT!q*0aHdRtzCOs5i*$9H}$qUXR_dCHHp|syOH%q?31z29G zd}i$U;pcRM(2A6x#6NbvFwqh&kUE;mZEFJ-W*!m!Jw248_}G}HGE7GI&6N)qZ(%c2 zci3Y^N{h`$-Zskf>jo{bd9((kd`lJB;#row zlYtsn0G(P6gN?Gx0EaNQRVj|{JV{lSp$M@Abok(JjUMz+VUlQjR#CWPG)$@n5=8~d0; z8D=$k1}WFj&CEUpMCgIq($doP-d>O#7dV>h!qJw`&5ASoeNkT^s3hIr)8tZ%}DNtBK?=f92ipI92U+&^fk!9Y7BlPTsou*v@Z^cP?-R(CnFD-rR#EEj@+& z#x#1;GePStHN3aq9k5Y>i3O`Pu5Q4p+ZWv%?|gH} zdr{<8e+wLUI9CqBMc#Y%V#Cpt{$_}?aeSX#%M5#YTD18@(%w*tDgo4%GiL^y8Nd+DxX@H|vY028# z>;=F4g!`pz1O`g7^Dut;ExRy#6espfIqk2{l1pn1_>KD*ikGEGa7n3=$xijRhYTC# zynJ8olTTEon1$zk^qrM~;f zjVWh<4#M&!nCJPiN)!9v>uIgdbh6NDy-+{riEzE`zeRclz$j^cqr=Iq6pR1yrFnPG zBPYE)z-3h4;8i6`3F&VTrX&|>r8=`4qQmDFLc3LMW=_*HH)|jn>GolDBvSK3EWG`T zv;$A8q)?Kt?P*WS9y5}(UDSV<#tow>pVZHY=no{)y@F|r0N>7?W z_t6EEJe#*rO7pi#Y#y2Z!AwgLo|}8`toja~nO2S?jm(UW8g7noKUk~xdPMd`t0IRf z06+R}#pC(f&n15Er!>DYEpgvUC(?!QBlB7X`SaGUZOtOm)_hY~M^Z0~B-p>xC)%vC zobPru+c!lj-HXMPUtN&6&5g{APfKs=xzAzb zjPw&%qRk;)&konn1hH0s$Z{|Wsz-2l2 zUV1e-(cdeeavknmx7lP!-=o0S>dWKOYgrhztVKAhW2)+Kgkn z_S$(zHk4MYhFp7?uer}MiV{w&X-8C~(xnCz=)qdAg{l0ttJH3tT}K{i4lU9CuoA7K zbj=fWfn)VDl~StGyUxgO$|d#78kf&$CLKD}ukTxqu5XCoYV&7fv2KGGaeZ?h58{hU zDIaCtnDz1%Qhfg3U}aEP@}-I<&bJ40Jx#t*jO>mhVGHB5^}6pygGnl9u)bEmdN%^y zEvJ^W2^!mVN)C_VN<3^j$wX_!Kdahc`gLd z8t^*(==l9~aV3eH394O&?6~ZG8TJ=0cY1Q280d#J!(=C$5Pmga769L(V`awbE}(E1 zVRzWwy5uZ($;hB-%$pEAH?8GGC020-#DljAO*vP2F*(~4-yok*Vd&=;$^6HXfP?papg2oz^Y&Vk4)CmuR@S1Q)Tcxci-!kwn>V?hO*Yz2#$U4Y~*oAZU< zCJef#B5(E>gU*e!UXo=mbb9-y0|V~w4L_7&XJfrf?z{ZvUn}if#azgq*dI)q)Tcjm zu(Zh}4wtWL8a2O8u%1#b_&@h8yAHQDMj|du4%wZPji&i~b%lM6KAQ4V&ir`7EW;2P z8}{{~cTC`*S(X~~2kXr?)KiGD5cg+%WYfzMLA?OHyx91z7xk+dI_SRt zhK=w6XIMrXJ1N4~?_+jA#Yz)xkNx=jPQzipF>zS*-v@`B+Ql%bcjYNoLWwk6n^HrA$$V`! z2&@HY$7Lbuob@o4E5N+H-<_&&yx5TBZAt4X!Y7R{{-(WmR`rM>{Y$;+#ns2PhC!J5 zLiNggR8sw>U%X3em&()-ykun0 z7fg*Mvt%Q22bGi#qr6Z0wXG>Y1Xx)^(QX9YAI!+e$*&pr0Z<_c8*5Qa4szB17(+YzXSIr1~be>*q*{tzQ5ZD;>an5c=oj zGk*%TrONhF9!Ku|gnN8A7TWt;9_s2*CszO-lKw}KPyGmlCmEyps3ze2IgU_Nmuxnc znPyyljZ&6*!T*&W)9lu&o|%q~t^X&@V~9Ubb(BnSR2}yv;S(15;q5)Hhk5&7k1H-b z6uQ|}pVG0iM(-_yS)~^m5`U{)y%|;{iFbOH7K_V@VroU?r=&oWtKMqljkmVLF<$7I zV);5u%W!{U3p7e&bUb+sEW@KcReMYiql{kck%m9%mgI2}Fc4Q}@^^Xs$#RV#-?Z3k z6U?4WX7){bb5rNV0lh4>Ea@0%8Rl~ZR9Sh*V~XWKR{$mrpQu$RFMj0uF?5)SBbWDw z_x(M&e?A&D9h3pQ&KJX?iOWvZW0w&=YwDrTDQy*zMC;!s4Q*k$zjbRub$@aUzdci1p?SpOdq) zuu2jO2C!Fsn|j~<)9Z1>wQZUh%AMR%7f?7rN$_1bfvK$*0tNnDqbb%5sXp7CtHvLuW4#=qDW0i{~;Bty8E(Dz~ zwaO)A@5yxP+hD$OeBtB`>k|c*Dz4#<(?ckoKSt87~re(J*y@LYL!Jcm$`z{zXDA2cL(3rbtOTt2#wKa@iQSs6Q zNiiM<1C#QC*ln+$)5u?3416)^if#ChD|<9Uu_QJ`wd1JD!Qs9v@x5Rpxbf&_&9$eh&U+^)>*%rUDqg&np(E^USqi9R%f{IjSo}4x$ zLoDGs*RBKv*ImyKKNGL7W0j@LwHdQ)+$?~9DkQd%4r`zs%_H6&UZY9dl2DN^Ip`Md zufF&wPekq3Hx1_l z`A*x49zh(+!B(NQjP>t{$TNrgEaq{=38&W!S$Z73TYBv_b=H;db9JgXyS=Rkj9&03 z8>fiY6tZ~habu$%TpKaXe!ogHh_5T~ya3cq1cs{A zz+3wtba`{o3d#zk?%2JNdCa-o)+aXl_n{Bj;lDlh zFCr=&TWs8JWA1kav?RnS^kIv?{DX1lRj|O$;D>uE|D5~o5A~z-{`n3Y6`q#xc$5BB z1u#Vn>&`<0^67MqnimP#I)KPK+Avgw2o^xLg7 zj?|n=HPTin5Yd_#&@aCD&{p3*lYPj9S(ed6^Zi z!^o8*3QE~uPF{#RgU=+F2_>@0+?$fv+XRc)4%}HmG5BZ(YpcECuK7>eUZ@u;w3>9t z)Gp{l3OXkOnX~NwzArdhGaB6aLZiDR{~y+R)3jjv=nVZTjSfNN#-VRRCBufeBlX(Y zLxOic-DohNE7r-+h) z9UoX~b->R+;rKypRAt_awraf>X_K`*HY+GxAwNo-OjCj0euBS@b1I@6iC>3v>bcVh z>v>y0`^GLd+TBaljG6v8|A=n{FVg`IYDZk7bi>Hc&_D5 zx%~dAH+AbFJHk0KuI-!jEj)dl$St=YlQrhD>4xWMg%b1yfGK+fQx@@oG(eCVPEP1im@AGBW#Zj!T4$e$y2{CRrq+muC;((3wep7BKgS zYDLMrlFsN;Ev3VOUm)3E@G|%qvmNl-JLx7?kjR;z#w+~PAp&8PLScmLSJdL>FLS0I zuzTtu=j=k(V8!EmgQBh-??c2F=m&pE?`@ z=iYF>0>nrha(9g5hvLEK(L70oZ)sm^+&rA|Rl@o)r)x|EIrVlXua16aNAyFM zk=e|Uot)mWfsS><W?%*3d+5+z*$ry7)= zfn^GxL4no!JbSE`6Wn*0M4xIW`at@TB|_ix_@1o?xRxlGWi&By+sD6+|?aQc;#=oYXzbMnSa?(aWRl`cTs@7x!x3^XHa_v_{oV{m2Rveso#; zvz^#s7qNV6-d?cmT~M%*`SuwUt?p?aapsUZJB`KPP1=?>wrFVrov}rUKf()c(eN zk^cC$IMdlfFKh4z>0by2vmjrRD<6QBMCAsq1TdQ;MyB28ID zAzs-Lo_@R2D9ptN`8ZpnB$Z@>+T(l?7ZK)|Gw-}(NhL1-mP0n_y1;XLklKC0W)=@n zy2Z0P=O@hdrxX;`WymcXXa{9eil2v)=k<+*QWCCYe4xuq@gwp-0N?@LaMKA?Hlzs* zv!dM%hUpBhoJLfMOMVk#Z76^oWwI25cL0#D%-o|J2a$2~Iztl6>Q3N3-6{Z~c?BRw zXT|YQDJ0npq-Em@_=CyKU{o}B(fruA$wRvbdeM)1j3sHVf|ZrB1Btl`+rfG8$(o35 zAK)J%LLQCcAF*e`ai^d!pRK3L$joAyI3S8vGJy;MCEP6UzirXc)6*| zLMSqT(6vt!tPuM9-}paX$o%<$2dtF1eoVC?=Vp;n_I^nze^l&wQ=5;82im=arY9qI zABR(W20|wfL?SxP&20p}!`}~R63uPHWdnHgbn&V79QMX6Au6gEV&lYHPcV(cXsK89 zMmuhs9{40+^Hwh#?h(1V0eR-hNnoJ+=ped&J$=U|c;3NrB%^i~1uFZ!U&V`_u6T_+&pSM)XyKFULu1g zhO+3{_JRFBQ*A{K4rT`!*0MC#-i~b?L{nGmFXk}u;I$N2_)_*wJK`O`pKy9TX3k$! z$@+m)xSYD~7Nv~m&#Cm;O&&06r@L`{G|#-3F!+-F3Q(dbRov**E$%Jt`?sTaaQi!l z+t8T(4`Qkj`XDB5+7O7{mO3o@n)Y%Y{`t4Ddj3UL!}pVN*ulxj@n-LbOKXxp2p_*r z&*MiPY7GBn)JdTDnunANwuFiuDN#kquzGSH@1c%PBe%rPAEu+HTrwqD0pt0uoLB4+ zr?2*-)3g7d6PE0l{ITHwtBXJDkY+@JCLT4}M z4K#*k0mLKhx6dqye9}@JW>G@?#Zvt|4-=UjW9;#6AiAE8#q)5)wKt29yHTR0+H+S_ zKQ#WC&%Iz9Z(pB-W)jhfk!LacdN`{d0k=zxj0FYNr!FPz{ZL%+Gx2C)n7d;6Ju7rZ z$0sdiMK;@b2ahS8ycOim=40m=5n;h>&uuS~?MgiSmf>=yO%iWk3zPYWQj}j8>Bd@v z^JTX_R#csow2KhKo=+F;+j2`Hpbe9%Md7Hr|S5TA2zJ;cb*TSZe)Sxvt)6_5}R zCc9y+habfOKC^>ZYpv9>VJDOCqPA#%ac|Rd(yX;jT^TV&BPXfG2pfzxgWe~n{Fdcym@J#MRiyJz|7f-GE(9)9z zZU{{dxY=3m%r^HiEjeUt&=rju)CA&)GY;Z=TT=Y&;;UpTBGK<)Z$ifi`OIE^ZuoN#PQeZOsXw&wuTI8vNULhBSLcdp%?!(?SezuZtrQZ1K-(3MIwZr+A- zsjKtqD$E~SnWfx{pX#7hV!Hu(G4U}~D_8ir0zlW;Txj;hY&50RG#BzrvB8;6GZ`Jg zV{e%KX69E{Jh+d|soMW-sfXH9)|`?TX689HQd&(1X15stB69gwF<6Bqs)#{&9r!Je z{(^FAjQX%RzPCvtEIv{lIja)gmvRons-#2xoJ@3X`^pl0Wtz93(s%6E`!gC8FZI&I zo&foOar0Q}sQZo^($+r1$Lm2<5!=2^44qLbCWFc$4>t@)X*gTA!>LMt2I56FT!8V8 z#)i^AY)d3hNxOsuvUVSoAvw6wDf%}RBhlJ-WP@DQI(}#itfJ8xkdcVO^Y`G&koT} zUDa~sh;fwITb!X&X`%lHV_j}2?k8E&i1*w3*>;FoN&(xeXQp&)Is1zVMZDud#F6}v zfd2}0D#L#C6Fa%16|MW4SVk>}7FrTX&fH=JX68;~-@cCHy~Ezg@ao!69}vwH`73Sz z7Od2Q_rS&x2AZQpJUzo)=MNrHH_6)&MqWMeLc^AFPonzT# zoBz^s@d{9-f?TuIm${CVhoXMu3yz*No3fr|m_Gy(r8s_EBV?JTSHKgqXv7oDdCeK> z=vU!IEn)NbWeDBxKO6OuZBv;$TLU_GeOQgFME)ztBB*JYo^qPZ%ryx{ND854Rl@x% zI-vvWlV;sVSCfpK6kc6=Uy}Fb5v7U>b(lF^R2ZEz#@D*UmeR^p%A*|vDtb-@Ho5z1JbJ%owC5y@ z3Kl%OXpe&FN)hxWQ^g^iv@g$=PtjYXH7#YQk2LL8l$kWhx%|J_py4^6K29>;mjt)9 z&5-t#?^aZxSnxd7DOs5LH%bhcCEpzOeiWKnHgQRPYKl|Dw?;%2idqqhW{pQm{Im^S;GKcEz;(S5Xt za-}P@d)h$@PUy!w4EG}=@{{ru#_sx%&7tSs)ZuEtR)1=5XCtRl@>^2xX)h%_i$J&t zZWEsCfCf0KZ?H^Vy2hx+fK~=qr%`@xF4{UizAQDr-dPoEH=Q7C2R7>P1JC5V=Qp!- zHrfW6pTc|rrut(*jq&D$`2B$LAg}(L^fCz6XO+f~VdNYG!>zuI!`j?j9w%nX5~$UI zosT0~yF3QX9Gj;#!fS}>;h{aM;xqerzT+Y25}I*~?M90hrH65VQylGpDo z52>M%3!{s=_m*1DHkHPDnEFr8hF#vPK@D-j!O!iZX4{TpRDsJUwEKdC@nvb5!IQB{ zV2@uDT8{V4o>GCis&mVwtOtWTom#lF>oJ8Ax!D4G+?GN=CT>tr<(hoIcd6@m;`D$Z)e3JbWF3$pxesCUtd>W4M z?v3rt2s=;k)J&P=g$M2!7uXg0z!jlafXRy{=%_wedusgU442Oc7UAi~T~D}ty9-Sn zDzyCrd;jYAuw4M<>^4z!TRTg|tGzpx1g`^oqcSI)G|rOqvLkrfdFM%i!#F2`Qs7GNwRwpFOE!zs#+Era}CXpqcoi+ zMF&7k7YcI0?H~NSiqH{1_c1Nr4$Seirecvvh?pCuLpix@k}65OYb;hjoeW<<04OR_-$m4` z6~i$obP+Ksb+wSJqgKF8vg=pniT=5eXhXZwW5R(*Rio~ZtA_gE>pdWJg}JF80$ zdx8m^qQ{&{V@eK(ikYz-zw=t^+S%kv2u|)_wBXl>_{I1Y@JK!2x(cg3=@O%Ey>?(* zK~oTKFvLe$LN5#*;g3I&{JUXA?4h9aznmzK5t1{hYE($S=+=G4_jqtOQ0zJv=lrtO zEQ0PoRXNTZNd+=x)%WXL&VKqF{l&Z>S}U&OOZv=${SorP>wRogPa3FfXHY-2BUz_X_xg3|65c(TBb|AUwGy#_ZpCvSe?08jjT)LfSTf=n-u-Uq@banp(kxPdPTGgoOW}`!Jl7$`bd4?aXIN=0oLVC z;-?9To4do1!*hLQda|AiA;~Nk=*t>kZg#p+@vY0bAO|35&!tH{(@bLAwmtWNsEALwXRPmG&bYP4-N8rW5&_uN+DZemtVR7SU6nY;-`l>+ zvm47k&7{d8#ONE&QoT~!UZQ|W&nMLUTHtzde8G=FwAU5DMu~%M)i2L6$q>Dy_{E!0 z-!*2lV_XAIj!M+~M}1(L&6iK7(~b3(fnZ5*Nx*|PRC;ds5)`&+34UVFWDw*4UFEHy zlVpm2=c)fja(nNQmTiOxdZnc!kt8F0V{DV6;?f6B<%a;$C%|i;k?kfwlQhobIMyR)L0O)_1a+cb4j!TOk`lu>Hu$U#TTJcUpvDvB_JebWz;%T*h1c zS{ts#X8Qyh-bTm>6P1@Q#I8zZs0;E5zc>3z`0$R?(0^_# z+;bWUmP!9YbZJdhja-Vou>9L{$nZxcWBY!68h^vGxgzw2PO1#0i%(4eJdg1g{uc~a zuH37K<93Vt+bIP`mT<5ykmu zhQf60rc1{JM{kp0ltITrZ9QksP0O|A6Ut*nPQ67U-=b(G%GH@kG;0Qr{+Qu7`ZoUP zhmX&7Euu>Gd1{nma&GFyDm4RLn2dHOOd_EU5Xs8>t#)|j(q zV@tyK-1OHK75I~%@Gf5ZKiVWnP68%~!?fi>zq@1G(L?@|nPXC>U9*~+H(+ND>VDzj4XzZKVX7x81Mkul~r#>L(f`TcMUk!Ry zK}^$&u=Z~!ll$2r1PN{sBSce!5A*kOP?n>OklmWTyJ8r^5RB+uZdzOyf=+^}H&YT{ z5#IXjJ@xhVajKKy#P=}3yH7({c*IQW*7^6!`AZmGABVHV!dA;XUNfh3{x9 zC*9_GACB%C8N?br7h>agD@2Dy2`}z_sBH{am9B~w%X_Nzl zr}kLkyvsy#=NZ|}0nc7630SK8iwL={$|*dIR>W}fa!jAFdz%i7MIa<4$3>vT7A@f5yi;hI60o!QLWNvqbvm$ zD$hZdt)>q=AdwLh-K_TuSYPUz>A)SxGtF<8gSTe+Q;@d-A#{pJ7R&t28HdeU19FzO zOoC!)`G=xoaR70wL=9bq!~IKJA}e6D?u6Hud0L_6L~RQ?7=~HglapjJ#osVrdjb3? z!%)}o$jtUEvdi7c<3*Nn{P58<>gAx(P9#g6bRh9s|M>=Dz3opuw=mSIba;lT!2IOo z4}Ii)Yr)L7`@XkRKHP*B#k@K?Md%!qxQLE!estGy;QaVN2$cmiCzPEvb?Zn@5h5saHqBPR?g2 zQAKR|R{i>m4W4xZv&T<*-pnFvM>ixg(2`c9(5!@6Uy)$>u0uv9g=%Vxu-i+AiTTfk zRrgxzV3BA9Y%-^nR`j zBxDzvsSsx9X|bPJ-wI({ys)_BMf&f58T`>u6^K|7P#O{NI!TE^|05&* z?lKhooQY~V<WsI-+e=M~CXS3|DFNis_|FPKM}liNdcjiaV|yD>jIV3cIp5>kYUFsO7QC(H(-cb-9RZN2}25{ zc(_vr{*$f$WahApzTX!dW5UL@Yel}{H+#&;q-gpYNRSEA!19lh-|ClmqrM^drqzJz zC)tSJS|+(bngK!2c%;o{2}^m4`oaV1LKtDlAB77Y--IrH)J|BmF*V7<#K(VDpKvjJ z7kW~dlBv-qIq$XqePWIDG$p>QF*vSnzb`@yx+;ny1aniEXm;Sn41Kf`%o0^OpxBuv$E>NOBG{}<#rmz_UdSs*3@&Vx@F13Ms#pKEaJ=a;KpfVW8d>$TOi~Y?_`AD}0 z{4q$%+F^-KY|JMDDJ$qzg!S{}P19?Xt!8XV4mreOBNzki7PU8$VGkB5&*kU+;14sX zq4ha8rg)Ldy3h;pmy7qn*gqL_=_X~6Z3Zqv~^SwF_?LVF3<~@ zNrgmHaH`}7iyy2pU>j%(sO*Gz*LCU$zve0s45-$1c&&QbYpS4QXc7mvB+ zIo9ymxSO#;5wGUXJ(m#m5Jo05uWRB%2&X7moiA>I=l>w>y!+XFih>rACcVTM)A;z9_LrsZvq1RDaj~5bpc;1pE=_>pDN@ z=Qxh{(YJ3jsz&?Um&?(3@b8kZwi3`Apgs);h!fkbzNZ`^hwzE}yQe{k2;!)A9z8>o~er zu%a7b%F!y?MDgDr7D5zohiI4o`4cT6GUdDXMWc;ovzze@h>uWlz8L=_8uV zFUYI=E%M#q@0iEt5e=dtaOnqXPD^ZUZP|PbFM&@oozkZ<5vAwtIO&LjJGv+Hcmp`Q zR$4BvPZ}eGskyby|c&`Y_7nt zTlkUKJ`OjfD6`Z{J|BYl5%8F{Gv%SfYvl+WHpHu|Z+amjxApZB^xmfrie}=%ty_T) z7jpr54m~qvB1plCeAm&mqkBAO1O2)YNhjUnaOAmF6gWA#?w(80`y3jYUx=QV?X(pbs*FimAcn4kUrlUN|Fe|Lb_xT1CUX4%(NYus~W*gsHn zD!tVDyizfzV#7G)&O`{8%YyZZDh40RO&9z1QH1x=Ls`+G@r+?jEJo18HIP^jJwiv+ z%Veid6vmC$Q2%mo{A>uFVT8q29-}WfE=R6=4K7y%ZA6XuIW(#=gXdFg z*X>JI>G&a`pwf`d-sjIyeQ=_qL4$W|{wQ8z?)E0=hpXMG^^V+Q8tWQ6TND+A>&^?Z zQ=*@MOI!W$Eb>wMFW$rf75T)^qXxs<%sq7K;66uyK{E z>Iy@54g2)W9IlO#1b?zcyS2$$^E7t9i3}EB4?~ZMcQJTy9e8fqrgROqwG6eM3qx#Viv*c70Kpq64dvegj`99^3JwqGqPlfTCMW+8&dFVr*3#xS1~y9P5?x zLlx6ny(!I~kiF%zmbrAx0L7G+izWO?Lnxz{7S+B5>u<8$or0f9=JeIYCUiHmxDCVX zES)?vGaJvO2jBtHoZNJcqDiz4k=2rXQNg!c4BaaVhYdx(L%W?k{Xeb+eMwZgFBu~U z=Pk+A(S02LgL!znEi*A zW?60Rju$T5y78NX;fvU!f(`=sMnDa#Rhrf$zB~=H!6D$wvsZuRqcxeS%E4m(&BJpf z{Hn@r(6j|ZpifMy+PRs(RiKpb9|-dEeF`B9u-wEO_Yddz(!PJHe(l^*fNAMgVucf{ zoJ@`&g2JXLeOBTMe6{7*&3wxYPB9!*H^j=6ks^6Mjo&syV*V;OuuuI1nKD?7NImiz z$5&MPSOpk2N)ZJn5pQi4uMlUjKvNVM&qL&#t9w^Tmc|J;6NwHPkhMymW41rC+keNw zvtMmWQ!%tDpHj{{X+olwGqgzr^t~!76OR3`v>S?A0II3_j;!GIr+~H=swCmaY+)=J zm|u*6%ZS|7RJRYwHj>zl?r&Tl0GO&6D z2GQ?g44#o<7Dq5dsd3LlNt$ zlpg`m7U4n-aep6Uk<9JoQJu=f?t)q5<9cuYyCw1xr0@=+jk_M%8$h@wT5Of}Oba)g zcD~JCNkz{;ek!&YhHf}~a~1x;{E@-ak0=hD|9oI~@f3!lasZ^ce4iQPolDeTO%`8SWh)(t4YV^wg(0 zRTZ--Pm3e1`#ZxekIfJbgy`KKP?W*r!pP?bv^@dN0Rs-?=pa-kA)Mej)BJz~c0V3HcF(Q6ynI|Uq3BGuOIhwLa_ zg$>ShjX&Q|>8gAC`VjrzzuiNQUC*iRg4AL(`$=Hid@8t8%TDM!Hs`2@?n4wMd)M4! zaCMk}Xo+AU`-Y^mMKXq5;0GIjrgD12htD($F!Iy70W^DScSW#|H0u|=e6SHjFXO25 zF}vCDCn41tFt8F*;;qgZK)vPHqetBS>FIJbU)m17G-++-iqH|tPRm&~;>;^kj4WT` zzeN7V%p#HhK+!$l7+J4(*1lYRKjpu<3hb%iPjbi36PgURY{L`;Rlo%r$AznZFfpP9 zlCJryrQDM1?m335A3nTmw4;JS2{5<+yX{7G7y{oI1+t^oLbUX)8N>OR*u~x7=-E{1 z@s-EBdr#_;W@p%kY2?Wt-KNej#9;2M3WKDl!rHkPiO1;dc%@>IlADLVcZ5M~FF-3c z7>$Ea^nX&H+S*LEKsDS%@&ki9U)jldvdakRkosGqOdMxc?BE|qC+orX!$?BJ7 zj6R~aGtN=V5|015fnK$UJ8s#Bx@it-eN7Y%ej{I)dfTjSzt?4-+YhQNW?z}3=GY3s zbS1Hrl~n`)#=v^sPDNRB?WwpLh&^b-y60^ki%5o2Y17BS-Y`qUE8AKtKFaFHG-;{h zG}m2Zj#Wc%kv0Q-Q~atix}TilgEBfE8<39(`6sR?x%hg|%e*2m2X?P&hjMQWB|3c5 zOz;l<%+Ag3+7@W|XVDGno_)C;v z{{U$yE0jiK(i8Trl3MAW8Ef^}6KJ<8_@c2rcvb@G%Bj+J?i2vsqfAN_)Cve;KO;X; zz5W9}#U>p`pI3z@KB9i#dj?J*9m4KD2>`a74m5*-v$ihnnZy(HZwB7Z&PNAHKF}?? zg6r41+LVY5vOx%o`*#b$jge+22t@ju2D3vsSdD4e)oHhX*p)`A+Bx+G&S=7?yAP)=~Zz<}!7c%y#q? zx$}&5Z|(t2M3$NCJ?mmBiMSUQel;olTkSma{6ZfoR}!eYpU~V=V31ZktH$PbDVE>Z z^rRnNiDKS6M!%Kk&0!?t4KJRN2P!`4l(`{}1o*C#`RhPUqhu5yq9_k5bR%{BlRJ zV0yJwdcOo-U-2I#@--bd4~#{k@ON%jr_CpLxM5iX1zFnxcla%jn#f2dlkS)DJ61qM z0Zs||h*2odAbEug6&sC6yE;Kn;L>$&>>Kf=G6;R_a4N~(t)ej6#@#=zz8Y>L4Qq$& zgrO(>edX^Nw=;jb^|?HE!~i$*-2WNgl;6-PMN@p<<>AdL-Br~#vj@l+tt0I_o+F}j z_6ys8lm}e&i0Hj5%ljFL_Um4XcdGKgm86LF37)j1P!0skJfpvuFJguIluO?JxIkdh z=E>ZE>Yt_BmN|uG%MtQ<;fAzWIIn3|8#_Lg_6ievKTNQpL*^7FYuRyvMlmRU$t7Uj zxD2+L2oJF`1q0DO;s%A^42jc=$4B|$IenZ8CAra0dmhk*JWwz9a=Yk-Cs+OQ(s<5L zmdBwj)$zWo)fR{+#1%jaoaLfvy2y*a{{GEP7sxy|mWE=#3Ji7Y%6Q$65c6h%_CZkd zV|)b$|Cu%IwLzaz3$7d8{2=(;=4Zy7(F{pLR~;0;0mqIV=!p_BBiLJ8Z$LjN;@f*n z8N$^Avfi423n8BlddptC1Ph6ndg?}bk@&RRFFi}Us?pHO6cuwx>>teGw3XKbjrDou z=DOUyJrN)iy9M=2N@BZaeQDlM+1cJ}#=>JVb7F2i}}pTFLJl`uvu zX0B#)Ofmw2`AFJZegWJc2G)@y-y>Guq+r|r_U?4qI|NcAy*;SWCWBJ^=CJr@YLWw4 zhkGR~)pf@$6xI6|IyR~5OWw&0bV`2Du9Y~>9jv+D4vvZ}%hFIKHxlS+_TYdLvck*Y zpw4sWi=@fH;rwxe41KL?`V?@JAP9x$w6BWi2Uo3z@J z@Bg*q;FuUrzRXbwn4G(W?g1>lKAj7SYn;htONdT%%q({8vWiTnfJl@nRQLE=mCkrQ z*?J~%IsA7eI7U+t>G6gq_5UhjBk`3B3pxHEU~ap~X!$~Rm9M_)&puT9R^z6-R`MqU zj(}wqL3DbLHl&os?}xS$E0f&I-z*kcSFVE1vyc$`eb*p&btZbM#+V9CVX;I-HtR(D z3ew&ZxC+_SAH1cpFcQe1DHl=Y9(-Tsc z_8pUW>W~L@;bmz=o5&7LOV1iq$%IwP828}bCVu$z!{>SDFOJ}Ra^jq`k8-&MSZZkgkV7{WWpIggMYnUc!1;-^rkP^wC}<=>bZ98w-%za*(`U`f57-e8e3)@ zZT99a@TNnDA)CUr#xRg$$-}F=e-g+7wL1jz$&1xL^&?=>y-}f!0Eg)ry=2m|&ruN- zHq^xW9|-$`l%dO_hE*=IV0eBY+FunWw*y5FGMDBk@e)XDdmnCI#t9^ls`GT47k=m3 z0)!?7Ini6>!%uhu3jz0J!{QXueFLCDyds%MYRGWHl*%geSx^k!)RN)XR(jP`2@)5+ z5fpx!g9XDuzxIG90{I3z&C&htBupcV=@5xKCmeHn#0|64kMPt?#s)EOc;Q+4&!(%- zV8+9^d``|84p97{zwCk&-oa>nJD0D_!O2Rz%N6wa!#nYhr)+%pU;J(1XV>uhrk_>d zYu#UX^;srUC?E(2iz<_sKXh8h3M;fElPyqoxP-)hhmH+-;ldeC2ZrrzsUDg;La!v` zIn6Ph8+S7$J8f9hUSwR=GMwp*BK{LrH}y(o60zMbmkTMq-uT!BLO1sH6IUveG;c;y zYGyu%%ZcFHc`45Pz^$_aSkXwKxLgCs;|dl{B~C9?{~nfw;@4lJ>rm<@VkzA@kp-4< zzimEDgJfnI`SkVCytbu{wwQvhmuQC8W70PZz4ZRts!F^=p4JAeq2t{YTAM)9Rj#TibIcCv<`1hRfdg|@DxI@8^=}T^j5m18P zW!!m2GqqccPropVA(f(TA`qA{arkGrU$RDGu>FI`i20U8#M~4T2hm6PmwAO4RD?UH z8dIx~o?!@hH?TCEiHhyBJpbE2gqL8>C)H~cHYu1(gYH89W)<5MlX>B3|s2 z3VKy@s}L+KYhBR%o8s&-Iy zd(i%h^D(+{{Aju;ou!ck-_%C9$KE~{y(8qhR@_vsz51qj^FWeaDg-p=xDTE4e1kn~ zS2#Qv%O*)SUW?%Wyys2A=p4@HqxRh2Ly~2bAne%IvC5<}AJ$T%;s5*}h)qNPnoxs01tk zYPT}8;w)>=FSNhqC}^fKHZSUR)d*Q77pdnA^12&~V6+m71Eo11D^nt+U8G32+-u{S zZrLB1MZf<6?W${Yu2J>gfX2=#)_yYN;lHQ%2*y@sxDuzsXi9JG3cXc`^LY2GRx4zc zmOA^+-hN}xmstd3MlJ(Q6!W#?kSV0bxSh%@5yOLjaKQt`HU>~ z9eQ{B&?b_Ra|ILZ!N>+jzRW)4wK$W4O1}-j;nqkizPd$79B+VITkkUR_m_VlA)WbG zI`Wxv03ng`hKt1L^u-Do)PQSS$ z%S~e!%%tGx+N`qmo&Vc-#EXzKo6oQS@)Pv)MK;^N)A{dcij39!Gd=S?--U{ZNw}H_ zVj-Vc%oG2Co-W7)SQf6lLl>@j{kl#f4Dm|A*0M8g`y?WD z(TLgEKT$?!cuV_-W2o%?)ulnZvl|5l0A+AZn*AS0Fua9w<}NmY{idyM*F+Jst410K zpo|3Sa7e;O{B^a{-cA4TQGKy)cB}PeXq#h<5|6z5I!Kkbcm2aVTChy-u3rFDP0dcx z{)uCE3E1CC7X;8bhdB|JI#1rrG(_c8>Te)jkc<~Ss%DhS42VOi~ zS*oy)g|%USL4|}+_jp(e)(1NZ*i}z}kYRRXp%8O(Iv7FuGHX_K&+Qofxi?WMO-fNn zJx}EL5E)FPBE14qIma7j3cJk2yw~^7>NFpf!wLz3LNxel#Iyx`M~W)t^$pX4v6xK| zy$4#Pnn(__b2E*dW|stWwvQ55%nT<@YczZq5Q}jd57z3I{vOpxa$Y8+v|(SPYQ&&& zUb-pLW@G~A&FtN;Z~LfVV&4&7|els*8 z5u>xl#tlIEZoyN0%IUNEw;kwl7xXpqiC!T&Ez7}k`=#{7Pq`PN&uA3AtP~A0xfxaj z8;t_SfMs$WskHrF;{r?hL9JB2m28phrNks%3DsixuNg|5n;V5*zJXwJ4pp&!LZ&HL zhcA0E0$EQ}4qb4DGUvV#pIyK|ko7>5((m7D< z5VG=cnMX>To6gB*5JDk>xaEv-dX0G;80aIqvFYxHE!t+ixuNczffXSvj4NrJD6uVD zMtl-iFd~JrqzMZ_2)8AY8r_{#Mp-G}a|+62f&H+R+C zDzkUZcz&0sWFCE~D|pfkcx2rYirLA(e`fN`QDl8EQTLHrcsP3JR?@3>#Yj-9G%584 zhNJ6a*xqBhrlnWSU-bt|GbKE@b8D+p~V#oA0;;D<^gQtT`SQDlbc_-1asZS;57iLZ zrAb-(#T?T|QQCnhse%nq6e_x2xLlEDMkz|+Q7nq;YDWN#OCH`7%(7sB+P@TxXs7JQ z`t3s77)JpLPjZP8|NQL~n0;N@*$m(H-ZR+aza#1A*QR7U6}kHN2^I8l$;9hkO4(He#VnFJ7;3$$*F|(}SczA0di=oEy zjmtYd48#}O0~R)qd_dYtO*n7u1TDq=Q0eM`#rXdNZ5mzP3Vww9dwFR@Z%DQrq`5(C zu{ZPkgUNF_dI=zZspg|se6{p`hy9;o$#ey(5>phNzOEAu6s-ccRnQ|Ia>4dD=g+q}caC~O{ zInSW4t}!1ry9#rxg-0a+1L?QY3|g935S))Mqr>K5Q3>g`We#!Hc}CvM@IEHyC({IF z!GPcBR)LpQx*pQ$Hx}k(E%GT6tJicXV(-Bh9Y|?JJsWLL6F%`Agb8MpBSP(e{+89& zIC>iVUd0jVhTE?jq-xX`3xs1<({a&nu~=KVkNuYq=Ni#Vv`s7vXB0qqq+xLeZ$E$% zaM!2fW?H2l?Am2s3!y~wyZ3eLFp>GIT_}zUq--v4N7<+CUisX{+7p}L+xeP}*fWVx zDl@X#?NcQdYuh8w@$3sz*dS92=7W8s2C!Ri6^G`6O1v0vu)rb)6@v|X0=N4NT5qeO`@~1EcVL}PiSar$3iDTC zlrx;8?OZG(mi0|RLe{y7s^N6UIEbB-ZS}l0ES2cs+l&8Q8)x;Co$%8cG+F;EWB(_Xm2DQ&3 z=z>_y*c6lxG7frk%jX|k9y6hR#uFV1O9UbHJely>KlEWOluh-akmYF_8t-D<4AA$=xQBesZm24r(l94RBj^Pt(!BL+nYYNI?x{n zYQ{IVoS<{s`z2<|6I^Xgmcqy`>!EL6b!KMsG#`xWx;5BDtq@ztVZS7s2#uQ#M(;2j zI?grHS~_VZDz*-4X^e2!fbN&Cq0q$w|+M?Jg2jk<}9iaP7Hv!GbPPs%(;yYAu}h92A!T4ZJRu}Cz#wE zfsluBFY-vZ0U|<%+)P6jT%ek6GxzL`_cX)90}J zMyzo9@f+#$?5d6P^U)Hj5u2&H#L=H3>GCiT#pDawHo(E0D@pH76 z(m~mGeAIWL)HgC!)9rJf0Y-deC=IW*baH^`415LzYG0|N_=UHlZ;xWNs{txt8h$@%fCYwAu>8`5Aa|sO{uJi^H9#Y<(8zYk&wJRFb51-0vSxr4sG9^d12R`o)k-l?a z*_+A$+dOlABOQUe;@|zh?6m@Gq4(S*DC6*k`yVPCh0q{35Mez(z81KzQsrO|@@EsqOR`nqM;+-EN+oNA| zz;V>7EhDWJaA-7g{Yhsc*cD18JPt|o;zn6^0EQd4&BI$90w;_aS>C3jVmRG#kz)Gx zh12f26Lj@&dwxA(vh0F^bl0UX?WT3Lea4jIARy;Vp{-(bXFk{9=9^u?|N7<$KE{9W zq4U>v{&y7DnnugM>7E%#bR~-b)T#$`TATPtHP<8i%Hc=yovD%V9Qoj#D7+sk zT<8e=`R-n9JbVI|+zOjIk{PzxQD0F;L2~q18vHSNoZ{94T`c>!*kqVjZpx-sIHh(V zudu&^%WpnMZ}0(?TbOvgDfK+-;AZ~1c;m}^mDwyeAYJ=d0x0GgaAokzjc%CMCe$A_N3@wWP^LB?+{MK@0NhMWP$WCUp0*Bj9DFMqH8fxMbx-7YBq zep!WQ{sX0S-?>X?_Q7>iepVbnba;4NJBD6bbX6hO@BLq}^?@wyC_#@=(Qr>_kN7%g zW|1{i&3&B631AN(H@nUM*f*Y0P~lns-VOtB@;sf5d01Zg4c)GO(%+4=(EVQ0 zFaCi{D8EmCui8Sg zyn$JI<4pN##C+}(JMB`=$zV$*0HFaQOega0Pc~U{;K$U(Yy=6$gcZ4AfU4H z``%UiPv3F}qHEM{tL$$0`gRz4PBC0qevR_G&{fl)&YZ{U%GXbi8;;RM_+oX4?~wc( z)g29&xd-&cw7G5{d98Y*3S|vc&mIm~x27{&)ej+}ydm~O2DgX(o;;~aB9O*U0|L%@ zW45%7woMTsB!{{+@LL1z3Xfk<6?xn%w+vr@2qdfgDwS*>!k3J07orjjXcC*mFR+ie3ecCZYbvi%>+N%9sOd5@-sS4PaEnnm*GyH=$9~}i} zb7p8SO4x5e-%%xNWnx$AarhvAetU#3Cw*}q>qL=C==CDNkfi^yD3ZW#QZx735gJ%ZGhXZaDodgOjd|W@$RIMK?2TvRb$SB}1 zM5}nZ+X@xvr@NFymE@;@R@Rl#D=6t4^%2xc9E2y-Zean%FvGbu1{vcQ)8X*47HQNn zz#tY+I5vpFh-n^f|77`FSC4;ZEr{tict^TeoM|i|riZS-DSS7RHK9Q!(~PaowZlVU zp;Q4o8q%3k8=awIjC@Jl&WIzF!{W^>iI30mCF{sqVrq^4ClgY~$Q_nb$W5 zT-BROj(>oZ_%EcnmL_)+_YxLE&_&|3IabEV!)@5u6#W-n;99(xwKVnNJ>;l&l~2DJ^Sg{5|)q5|>iK z8(Uk7NO{0s348?;C^FNBabxYezy-N|jToA3UomB@jsbQp(pe9ce|cJJ!iVl01=^7q zNr6oEpnWE*jYM<&c1K0c?a$76Omj;XtrsXC(bWhK-d$NIRg^T2GCuF}-imYgZ6AKC zA@9yl7p&yL{Rd*4hc(vRt%-~C;DG5}X!Y>=1RK%Q&BSgpCLHMUEmG>enur-H^4hLPTS1}OHc=fl_=EYF`pfOEUI^caYND2kY|FB z>PkDRHV?9`pS~j@qtMy5dlmJ4gLx(IM*heqftRsH^&B7k&@xg%ZBRs!QjqfxYkeJM z^LRp!us-a)Klj{C!#LkVboW4NkR;Cqg%rOEUwg~XHWd&^c?zI5-P#-+oiy=I&}RY`zhJ38IcXJx~>@t^f1u2!>A~xWq6)W=P9{g zFW9Ei^0z91+=bBSKCqc%Zk%fQ<3m;)LRKcq$8vQKS`ZrX^_&p-HA#WMgXX4WZ>!qT z8Xn8r2=|QHwDJqNoUy0ZMj)GrZ=EpT-h|LHn6A~iwS0^bLyVCLePVGkZ!r?0PA3Y4 zckm#iY0$}d31Za~y^d>7r^50qF6eH9lEAH_8hEiSwSrSi-hm9}%18X1Q8GUl1qspU zz*1{9hft)(#}uMV({eUWIK7OAawZ^m2>OMj8&jviw>g1Qn`cy3HFr28)E+InE0PU= zA6@lq1yv)h^Za@_lh5NQhU?dc=oJpae;|YQxnPJZ@q><^uSmb8(X!K%H|hE`q|E34 z;~6v5u>|ov+yjC7l11y{w|Kz}6%&vwWWztwPgisoHB;N>??p6$`An~ck!Yg&%7>wd zl>KqevK5(xV_K`X{fJ8iIo8W+tk-$Ha&j@;bE8`)d)QsKl#}8>5`VPl$MZuOeMNTt z;~%Jv>-B!y!F^();ppKvt+zyN-OS%^RJQIQKHLG>;;KIh8?Vg&{=paJ5hL=9zLTry z2LI74$UY4fdf^MjYgxzia11wlx()690gCwY;G{>S1}GdAK*gbXU{v6Lk*v-N&rrKN z`o4|i9;++m%1wG3(2x#ux}JqpuJr1TLme({ae?&GfFd=yA~}KA^gZ>jgY{*+k%d|! z>HnC8&O4pPlddZ7c=Oa%xPo--R0L>g=n40jWOI2SryTbGMOT7PI2zhq^2u?t${?P^ zhI>8d_xB-XmGnNMu0u_lej~14Ar+6p1mmmg&+wrGg0?+=pl`ex!d;bdDoI zE?T}lWk=`dOhL2h+F5B7gkdbV0!5^0w2W0C{LNhM=Dergp@z6%gtx%f88t`hl@4X9CQk{x_NsUx9MwWx1Z_#Me)6K_l0L z;VbNh#k^l6n{di_-?s}n5*n{L64n}4xzt&VJq@p#@6dh@nRZqI+{0yNXXfwd@VXzk za4r+c_A+gaWEc1+W4AJNFUW^}QiDI-uoDRDq9Et(nPE$Hs{Yh)I*LsjYHe6?Y3fJF zYUP^A7k_CTWaf!Z)&Ri7LLtfn5S9~JvqPfQFW8ml$^jJbEMw{aB?)vw4geeft+j@<%;O$m7O=Q z&f5X`4kRIqpvaR$Ggk!=6YhF`A#*d}wZC$HRSY3tif?QbAnh4Km;>gRYQ}<(yMopW z@(Y_tcWrJMu+KJm!fr3jBH0$bymoIl#GZ%1P4?bGUH|D%o|{?p-|C`B0J0}~`j1oR zkZ~|EGXh6ieb-a_zjgxN{w<~4)8m8HEhkDN3~a#{zSlx!v>rSu9RklxCDM&T&lmoI z7)=@Gz&fgI{nq+$b2ch>+L|`zpe<y9L@lxfSpd-Wm|6Hi}u4g>@%B zrYkjqPBdW;809X5T_=*|BRrcjChv?4-bl^%#xEmLB{(mxs$e@C(F+qdoZ8H-+Y(|C z`9e9ISrCYHnxcKyIEl*KTF?+;QTn@H<{#CPGPUef6V96uU8>InlE&R=-~_)_+)DQW zf36ykxJ*rJbhUixm{0!P=X=iGk-&{?o-)(-x~g~rEkh=Gq`LfNgpCA?THu^0%-Bxj zXqoT~=6ud2?m}RWxatoQ&ST{2N=|>D zE>}%PbP%$k+L~FLjA2Oi_7c zeu_1eODg{}!2I;JolmgDw_#Qm(ISB7e_s7d8jpFc5qQZESlw@UPe3}6l;T+pB6@EE zTF`rkheAgdo1LCV=}$cmbg4zlU~QoJUHBC})u>i|%BVVTrD^{=oD5L77UIFISFPwCvdw!gCLHbUNmAdo+y-h5Pv$WB_i3$#@e(rWa2^!GP@siLa1h)o8U~*40sdQ zc%jd?%x4>fo`ApfeYYiqpI#CdD5#z1i#;)RehfmEm5WQkN{fCkY1ASzQ|od9qx$Y3 zWA0O4p}H4Q1qj`T8`3WmK#!L~wNOAp<8@j;Z+IRES7o9X6d_tWJiA0ejvd@QQY72} zjkI1NcEY-=mv+1Rk9owU8B zR;ekkvM#$doM0ZJ*>u)&m`|Eafe!QYC8dCm)$XcGUUxXXp;xNIMn5W&5nn_(pa>Jb0tmB6dbv-%P-PJ>2x! zk0au9eU$#In%QJjbL6$0)klpHg^_;*+ILDj?PUYN}h)%tG z-yoVTkh3ff6>zA;eQ9YNEKNxG`BZ=wEXS9^i~ZD5Neg{xQ_Th>N=LdVDzl8pOVX4_otV$ z?CWJ4L*Mm?C+B#BiDHFKF;Qt}%xP>*S~T`g5VRgrTS_S0Y%h@bQ%_olEdi-w0NTic zVP5^y+=T1bcfyzd!0cDoKMhTYbMXz%_*NxMWFDU5y-;+rTo|@|bvDPv(z?3iIg1W_ zgu*5y1!$YHjy?ziglHPhrVUfExTcIXsuDSIx}NYkVW9U@);x1+JvqmcQKM$_J+{H6_BEK~@*pk&YL#8If^4bEOU}I0u~ggZ+BI>X+wFVD?43%-&87363l-$~v^9oc$_?w74V2~Pfzo2uPixmPV z7mtw+pe};^d}onQGvbbhvRNiI+a77pI>NafgNH42@~LbSF2e+eut#8V^~$@`Aq~Qd zj%H4o`_HHW%y_Q))pMgR+95Nk1_>*|Q{i5E3H8(A&kZO}DoCY~rKF!dscblU_&BGW zRk+r(sRkNi3B1NnRM4-Na0B8wHxu2{s(S6_&S44)4-8RJSC!0J1b_k!j-n5w;U){% zk!l?O0LhWcVFK|l#D%u}!G|%sxox`+q@`9J^)KimdZk21*tzY&uk$HSi7fh#ib%7> zBtl(qZ%GzZrMp58szbeHk|ItQ)lrbWb+=p(mq1mxQS}FZmvl_2AwS04ir?@jXn7qO zl)}93xoM(6>78C_IgnE?_RuKGB}MQd;%sb$+hZgBzJtf`?Up;VIFd8@+uD10zwc?X zq&!LE_peHpXy10QMg>8cLqy`9$WDAmupdB*85AR#CP4wN~E>Hi(f{KKg7 zEn6-lD$siL-6<=$B$wei6v9#? zhfM?LNN8U41nO;TNtXrD63qlRv~QNMP?iqbyiGgGqi3U7cMu|GyMWhw@A!grwTc#l^yhiIsMv8sBmIiD3*;Q6Sigg$K z1vdd(^{6dZWgB%o|0R)kgqtN=75y857@WwXx4X<=9`-}UHljynnEU0Pr#rD+f31f` zTlBG`TZa#GAU0O&+YPm*RTk|Wj*p`$>Q6}HH_D7TWYrMKuKDif$rDJ$=ux?M4cBw% zeqVS07tEjJVNvxS2OjV$zyRTw6EZQXDZv{lA)Z2ZN4fp{B^_O3Z4R974neRLu$sRH z1SYVDeEv6GIubsm#oaEd>=e4_Nr-TnU~W72?hzYHMM8QaIKg#xE7n)4QGk|i)9ZQp z!S!KnC+pAI;lpWDItWmt!;Kny4h*s9*Fr}X4s;(fs{98}wWpxhKgdQqfZgDLC+Dz0|5xd6Z&u_SUA79ZJ~jsUq~t&S zgI)6cdH;@2RP*WTOd>X@j_FTrjS9|;mQ9-M0b%9!C&;{5I9aTb)3Ve7oG zCL0O?amK0cRRJ$d9;Fc6k9gwOa~fvgo8_3N-q4%0>eOTk@M4cY0`~;`rFU zl+p14(wi>0Qkt6ibMA1~CN){LOFpH&nzwHm*M@g|^q|KnA-5X83w@Gy87ph<@wyP= zCn%i_TnZjFAWG}{cj!5}{3H^sbTyV@g|}Pue+hJuy12HxCbOq(Y@a5lXgE+fTH!n} z23(bQJcW>ttll?rr%mH|oze~|-O-R+eBG|_+@gXxJ>gR=^lx9(`+Ef6XN)?*7bbjm z;|b|EYX?cr-p%L8RLvqXTalH8gl=NVP8!0G zw@;WxpO?V&6BOJ_i)XIUf^9NEV<84DU4XIcFc&J9gU}Hb41S##N2w*dT1vea^nju5 zOdy$vk=Hg#hZi;3pFzl#ml#D{9}ui2ktxR2p+49+dR?PNQK!0zpDH46n|WM@wgz4m zeex)XZGxmrY9&)G`jx&s<`FtH9TI-TltRYhsUj5C)uwvP=c5u+7RyJ#4SGPR3-Z$7 zB)!finmmhpP}i~tu*2jL=zWew~wf>>6WeSqh7zf9Na2q#2 zp!(3s2_rt1E2gV^+6Hf%og<)pWZ_M>ycG%_QWb8=u4W)DMy8Mtp@v85umWn$$>@sY znoQ_#n^B%5fspoxc66aF9~r9> zC|(y8a*SOQxEe&Hgh)Ke8E*Q60%8Q8EhD$5MsCHdx4!XTUnu$2LSgrSD-G9rfEG0R z;d9$*Wh{g1o91XMhCo*Tb~Tkz>#cbRMKSA(=Mj@H2q}~kvB@Xs`1PjGUe(+B$%EyX z_GwEX2DhUiUm_ptl3qGe8nM}Hk&n;xk0Vtk_dCaje7)e!xVmfn@u=?N7XEaAwH}As z(NN7~ccJS_*!R}FF6Uy(BDrqXiF4b9G7fz=Nz<|^CQaeVxFhkOY4&gKRL1g{nZMs; z8Q{crcqQg{J1EDfeK3D!w~IVhCxuP@iBbBM>j*~*um4*2;z1?P;^7|j0uT$b1@_+! z3;Y9peXg%1zZEw8y8)$URW6MV-SkHVwrUVwGJg4Ase`v^O$&CU8OQ&Drs7B-AX&>e znEySUz*qA`dN`J(9RpMWH=;HoibL;0F!&sbI31Zma)R1jl}8-mj%S>Yu?6HHA1;XLWkhc_x45+m=1F^fh1>2>DRwtD%@luR_<**@akvIAdQ~V2Z+g+4=|C z5!-W{0fbs2y6KBoA9J}>c#c9%MWl0LtuCQJ6+J*Da7^5s?ESFWq^JutNFY-)gHD)a zXIS5q-7`l&`1_xM+nFi^va<2_&XSL+D^{LZVV|><|5q=U!Fokg9jFsiULT} zeRC&PBk>d?KDFAbi~~^*v3UIvUsnh9%rWkE?i~^;z?%9S;@sMPHSA1VO6K=w@s12s zX7=lV7pc?|Xy#9D_30EsDkN7J0t;1%3gxvpIS0BOBaTde0@KUFcgKL(4d~a1FO1y3 zN6T&vF@=TzHm()}fJ^C;KhDSk&9HYYxpmhRXpRh;u}4WruCN$mCi};)?p2$ia3?FX zh<<6US&v1&H{3_z!5|PIhUZgW`PckE%Fg?d&By)vvG*qSj=e|iBDPXeMb+Nb+A&J) zq*e)HtJ0`ZTGZaF_G}eJQHt0zYE$p${{9D_=T|@Gj@;LEu5(`JPXL!VHaAh3y7wDv z^vw0GdL}0~(pWx+edG$FtdwT(h6jQaaTkh7amkiQ;6C_WjY8kn|!8yyIobyI&UrN0D@=d%Wil%_!c z6Z^nMXfW-X|0ZkE8~M9B5<$;x5XcwGFshTX>7?wo7R_TXiU(Q>S0Sh5`JTHjN&7BW zzw^WLB27QwfffzjY-^DoV#kBHhULbtQ3L^4Uv+XTTs`a0pKDelvg{H+V-sdx*(1JR z2xZ`u>l)@|I6~&r%Tba1Hd6epj7(PQ_v=2QpXRM6Q~Ns8a#>EDpY1`T)@v|^*`y=p zGAM_cFm=vXlfhi7>@>_I%_<+<^afomH0|{~%Tc*|11}%rt|tQ`!xRj7-h+8UdRJW) z>babUpws@)A-7@F!rVN@ZyiWiFa+#D6D4;RY)HBVJ%1w%E0+#{T*ZDM>ilW`nT&wS#|qa-6l{JxrYJo6*N3FN+*R!rRTY$5 z!5t}5N75nPZfnK7=(N*Glr5Dr%E3RJm34o-ggu)O5EIXuN0BBrYj>ZUDVm>~;c8~! zHJv?+zo9=a4gFkGj1#xgm8S$r@h_AOX3g4D6wMyqfg1_cI*QP_t+I8&TH=lZ1M^k{ zo;JWB9qBSMlEM9w38BySDbt3h!})^WIdBy^OVQZt>$Q*8a5)7cxWv#~w4H_>3o z8>(FRW++DmBF5DoJK!U(lFdlp5$PAttA+Cq6HSn*?)K5)o$`v65!=8H4*nyEr z6Z@-MCbg=Wl($wsux;PJt;C2X3o+TTR3FQFg3g$h8NjkXw^8#|@l7 z6V11QpX;Iz>U`uCml52D8jSPGVw=+I4yPR-b{ObcO`G=H*tdh_nd~*hIDImH*Oqei zzD`*xs%{3p@9ksGxhIw|CiQ8Eb$Pv16SNC;E38;~LW)`ISt0;yPFtL(nf?W`I9yU` zTu&I%+OZgoPYL;je9Om?HgCz7GW)YRj_5W&u-eOw=v-bs_lCro`iccA{3zF;j%tmn zh5rXyT=^XuNp3dvhxlE`XqJf zMbmP-4S@u>^x=H_dQt>gG!b=9&5HCt07e{M3OlBXD;#e8;Wpf$^A2$Mc0hPpP@3;pw>AvVWE#N zYnReJ*G(ortRKFVS#t1X0=)tj9AMZ{bz1E&7@n+Ig;V@8boQ+PiC{`XS@W<3HyL2a zo}cxfrG*O>s&YX`ojl^_0vcItiqcU0JvhiFNWk=VTQ>aJc-k=eF?qj;BO`4S-B$|W%?N`i%=Y#~t3R7UOcPKO4F(6V9(EOH{d&6<75n`d zvqF*VVUx6i7KuPE(av47QE+^bwo67^3%~Ya;2`+t<{g#QaNk1=M_T9}>{tXoh>&mU zf!X>Eea~_gPa8;nw;mWU`$BXcyB)4xB3UeO&IR_<;i(`*!@nF>)eRezobByPo83HRLNS=&_@&*vLuq|-R5?jXiQct*UUwbL zwmJ>c`m=AoFe?an@23zB34P(WF~SFBjD|o|BO-_ zyC^@c&58-KAr>ZWAw=9elV_(Va8G9veJwpZ^ajXQ_B#gc}~2!dGS*Z;6uI= zj$;zFYL}8+S%~Nl>$03h2432mDSc_vOXT-+I`3|M7+*DkS1>61IikAk0^HbRW3z$7 z{ACj_+?VeE`scM=T{PqQuh@Zqc+6axVEbpHrmS2XA~NY*!bjyi1YuT4KQB#rb~&{> zpGXdEQN46a7)3i=Vt7~LxDiF9@yhF6o-Ey^0ZUvMml`$l(jKX2ACPC$^i_Z|RC?;5 zTq6N!L{zhtnP)=xz^gTS4Zwgn37FX$U5>w`W=Nsajb9$fu8y#XmxVdJMyzXTv>^~K z)ash}HVKFB6rM6&@eeOB9kxf{`P}2)akUu25jZ}A=u}ZP2Kv+GN`rO%)_Q#$VSF}B zBe1Wj`>69;p$x(8!<)yP)}OUZARX!gd)kte4m~4yK>iQuyIO#VAZWnF`FI_9_6zt%c?wkeyrM=R#z^`Mq_@)a1_Y>8y(=g`2H7z9&(6?w`)nk84Q~Zsi1<9p z=XPtP^sT*P1am!Qys1sa8mQ*3Hfu#omk+{%E1pxfmmkUfO0I}3BSs6FU1jT3+J z4zYY|_ONU3dHG!8&I_7BpH%h+xQHQbmYb6^=_G=>ALjBu<62nt;tatu?P(wGN*0hp z8EFRRiBkQ(t*!U(VR~Mz_+-*E=2Jge^Re*tGbFfLKzM8kk~?Qn3?xtaFU4^f&dmrn z&m!#QMO)s%o|arhNP6AtnxS8F5vtd9Ibh2_I`}_EA>>nXqCWwA$n@`uBLw>ibV`g} zj3@_!z`~=0fmq`B59RpFne+u4s2Z0+=V$JQ*zA5B2a@hDn=tz_LPw@=9HBJWj~K=y z_|?z-kq*!V=|F82LTEmdCqJ?mP)!S`3^LWBPcLgFzAaSs;p=__DAJh>j&$oWiyUY# z7~Ndzbg<$j0ThBLM{ov-YWoiE4g%g43fUcw*CBuQS38pp*0kh`0>Ty#AQf|-lZI~r zI4Lus6z#X>y2gQ)y#Vj+d-A=Zd`TSVxET>2?d-yzlCwXXI@q+K+Rh0}ZI1zGpUU<#G0b(rNh@g|Ga(LVd` zd6-scHp}bLo(9B*x+CqqX@EY7B!ffhTYSW;M7DKj&U?=I1E4%{(h29956Ve2K>$sd zwyt;nkP7iTurXRC%J25Rhxj@wgCQM(acJeIdQh>ZM4dx?*TCkMNtmKE@gt~lgxL{q zapMIQ%s6EhU3r2(Jm$&7wdh$(JbN{1{l}T`_4oAq>2;sJEQ}Y$2rd9>p#jT3m!O>pc-bc_{ zC+;t)wd`pV9+OEo4Lr08-Bm=DRu${A#(60ewCqM7bSB##v`B4iVvYzs&1(zj7-o#zvi)pw#CgTcMX;S6x zKfH8Om*LYs`7D_T8;$?h$f>9?X6H=EA&W#m=EirVORXO?LJ2q6CT}cCT_Alt!})*v z_jmT#^$#QO|7kWB3d*z4g!uF@}*bNibcAkRyahM@)UVf{m zYi&4QD6@N4+gq|iCCc&IWT^dGJ(20|8ufdcUW9#ADob%QOZ{LHzp#(ih2Yu(Rd*~Q zV{(qkI;gs{SEZa1ynv$WxrUkahr6SSN3z;iTm^zS>)~@6_>3@LbsE`c=`_Ie$)M1m zfZT+jlqt9!VlY2q);ivm45h?f$I9Y2X_!7dfM&Z(WdvN?Ue1g2YxkdsYbvy;QUG_{ z$;*zpPz$<(ENj>sqAYV?U~xK1eJ^-#IJ23T5iU$qgC%S3b8+!$V0`U5zLAYO&!cP9*9I@|IRymX4A_4WC7!#A#0X0Y z1!JSw`z?@9OoMx2IDR`ot5-~WgnB>1cRL4;wLHw`F29}6~o1$B>vy+tez;gkM@xf_w^T zEV`|#G7kfpYr1dmbrRlE8Wuvv!npV*I1h^u4CVK|G=S=}nx0{QcD?)4BRo&2K2w|F zo0?IVyee#ixulH|lu1eYQuSql+p_@=)xy@!?n??&29A&`1(58qoq!rqv}?X9@gc)EyMnGdA! zb%8vXQv*fF0@2T!7WS7^)&?S&P<{s(8)6iYI=Otr-}UKr4HCQw9_E$s{&IPSIWf*F zL#&?3(qCVH0*)+%W`D}*zBJfmoppYx0BA(ngwiiv3ta}q@Yp0fR&HX;C4?pnllVkP zL4WXm#a2f)2?ACHSLf0Md{aLNN@3=o@O?+;SaJ;W&qU^DDz`qM4e0JC5w*l8>u}JH zpI#>s@hiQAlx&{)s^-pIhP_V0#FNe3^N(7UNeiOI(e{GpVt?6g%kOFP_p5GMcn+Ea zg|72U;T{lYla@LNZl&#Yp&}a`dm~<7HYvOXb~D=a`dwX^EWGZ_I`8 zidrXua?f6b+UqfSLvlaewqf0_KOpxNd;McfddtJ{bB0_|LiYvwHcnq4r0ezckFI+w zIw#-8!sZkb?jay=woY1y&KxEYOTsTX=xo}7K95Oz%zgGN<7IN`Dl}j$)9Goo#Oxm$ z6fqUGRbQ&8?s_VkH^h*z0u-&av`^Z!+?B~7_}zA#HgQQ^kBl@M#K;3=PvnIhdJ!hF z)oSYrl&+R*b=<8%%o?0P&t{?N!0P3f#rgk0m8SoJD6j^l+1HF}-Q)9%n!-xIkjkts zf1Mu~@L06J ziY~@6a_SKnuGi-C%)63UxHqCIgGkmak(qy=@=K{R$V1&5OI71cTYWSJDgaGF_&8iG z60)V8Zi;@Msuqbq!ttWR2JJncaj@>|O}HdZ3DBfct|%6*Tu{Xl0%>iah?s^QZ(qQS zn{XSL=hd?7DiXk7+tRYecEOhJJ98*3QYIm(ldjcPW7eO>=+V_4F3fP}1hYW!MSr;F zwgIAD6yapGYf9U!&S^DRz>H@nsoPy{jWo}rNJcFN1LlkQWD)& zjlk4JxshuRRxm8gN2}dNPXR&|jmcTx7(~xW7#R{>8N80D9+w)n{SS0L!vB;==h-Wm%jyk> zAlaF^c^2TO3&_FeMykZ_u_c?nH9R}Rk@B3D)CyoQ_b%&AsNKmkH{wCCg~tqM%ZVib z&j`y@bI2aZ7qAixlv;8meRNR6x17zh1GQPpI}U$?g~UnYt@5ft-PX|{|wR697>+xmuppAlYevuO!-gOS%Sj?r41W>v%85M7SXymKy1`fHHKuR*&p)mS%iydISaM`- zK4TI8>h2F?&}``{dqCbql!7tkA}xuY2Cwm~_G;26vBi+zN?b=GL1kNIuUi|cKp33R za4nnR=+pE#!1K@mM6m5Ui|~Qy0Tz}=cm#>`aHk+V*J-1}2RKG{r4JQD<_b~IRdSp# zOS=k~n)IhXjOi7h3FAV(T*Nts(%~A3BSn24e2}*~*%<9s_z@OtX+uwi%3L}En2ko{ z$%7g3d|FBnD|&PG#hY>|_90hnCE1%WWK*=lD83yCa^Q%$m4dRdm?)SHexjCeI zgDwYDaXVq*+a}nA!SNdCHw`h&XJDdF=|2!%7m#qk$Jkj#6d@Kr(h~utmcJR6i7kW{ zYgH)HeN4x#XXyX5k@jZQ54y|+Gt)TT0%>V?;WWgs))(4Q1?S>xAX2DGZrLZ2!*_fX zhk8;@6IP%C3**yBdCm{7)0-8=;_MV!x{W6F4-J<7avedUhw!b3GPVub{6QY~q4$Lq zhS;Hrz0h&Q_=X8G-+rh%y9T4Xh zC^!@jjF37HpnHP&dMCcnHO0-ab)<$o(AJar@h*U^3LVW`b;6AKLE>zo1j2Qesdsux0q5SA4K8kKD@RfDgcM1Cx=_4yBAe5?6|$ z(1Ns_OZ;o2fX_rSf<Ly9AH1n`!S#Byj zRHzU@Q?vip@I8zneAjQ5LeF%Q$PDNSx(!#i9?E$_8KYPuTFNQXnH;u+pUO7AsOV1O zyZ=Btuiu0cntIl=ub^W1XC|L&WRLu#aMC*ohOzQnCAL~NR+DJyZY#aZ(C|;%E<*L~ z8t~_7$lZF}`-CXKJ63X%RVSi(FZzAP- zSCNqkm-GAw`i*hvQx*cxS4#^>Ue$KtG+F{c-5_>}XugCQ3aH}C4s4;~-3AkCfB%XB zw>q1|Pe$T3bBo2LWt->>?JE82p=+#$Vy?ODsijc3kjN+Gq(4rQVc$OAS-o8{^ zcwCb(UDk}@Y}D&IozMma4yzV$Q=4zi{2Q_~*NJ#kR>m(wmr<<@sYV^IX6CM(+1p5Y z4i#+7_mz=MTR0&Xgj1c7OFn)4J~q}S%QpciIUoy#SG%$t%c8}#cDI75T=rg&w)`^s z&RKtjb#%E`n#@HB%g-VnT!4jU@s*%N#Y7F3il4Ol{5~X8d36MJlgfHmX$biOfr4Vb zl;unfP5uXZNa$s<6k6-5Rxn?v^<~1#+v!lT^C$p14~+#I=gtRwy2}^P@%v^f_JvwB z-_y|1n5p;!yeU@RXyA60BDrD z7x#(Er8NF>e;q^eRfIpca4{G2Hfgt>o4z5Z)-#6V#@TaZmn^78lN{g?QqZSq7Im)^ z@THcRG{LI-AarIAKr5(b>Yt)2)ta0S_RfW zNFN7UH0~)!J(&BapX5F6RUk@*LL_f|6u6`fd*~zP;^#dV*#Nc;djnD*+xZVvVrAb4 z*a{Kxk#xL=`Ozvn0k`FHF{-?qS;`63<2lTy3YUmLfaP?lFBzPCVpZzx*1UKKR@o`% zHR<$)$|?0-e@#tfK~RUgJT%aqr`Ubi)xfUiI)7QH&&@CUuK}waE6)ASu5RuGC*A*7U5-OjR4&aL`u64s@)T}mRg|yGt3t4 zo7*%)Iy2#hGK5oAQYGxYqWUhTuj*7!WaMYQ{mlThGG{u7l&6GH@WIIjcfIa`fQmH3 zEG`3?J~w!bYiLjn`@&q;awhxx`ZTmYSwqMU#|slIisF5u`cWR{7h5h|o>}{_1(;5l z6-XYC<=I;YoABVcrmTQmlUNR){u}ih^afl(M}BzN*934(!QjQxq*((6W3i~q zH$C!EiJ>>>mbr-X`-S#f{@pM^8jmrBSlus95rGRxSZvFuBwbOvvLK!`8ZH%k>=Mj3 zYtt){OYfQUgFFS|b<5UmQ)>!J($bOa-UF8VO`@e)mFkW@!V-Ts`$O$n9^jI>@ZuTV zK)6Yp3e3+K<~@P|b`i8C4tXHviFT=7K)&cxl~dP>iEwSErD|@5223H0YsG>;BorG& z)Arb=V{%#)Te+uvn}FwYvJpp0_p?x>^wE;@+=_P9b<7usRj6SGB*0ZOq=vGnCa@$(l%-#F~X^Gl1?G!q?nnd7$y16OR$umEHAb&wOu9lNZlL) z;^m`pce5V*uTMk5Vvqbtn|qN3-}8l}V>z@9BduQ;%$}c~V)~dlwDXek(Yyv@V)Pg= zIm*Rp>b#M#TX}Qcc2NV#FfSJW8usi3L?6L9)}C3#K&=vMLC`oe z*eX*+r=s3qoG5V)h6mVva&f+~YeF$G;^#9IH#57%&O{UEm{ozEY(6JHGEcm*fLba=O8Tt)82X4nv$;?7u$b#jRbkM%3kO5#iN(N-9hsF*@# zhC^s(7@V)Si7I`e8mDy}R>>WYT$7S5S56jsxC_3$7p2N$scGg!(c)Y#gtZ5P0H6p@X*fl5O9V#76QM(*WigZp<_&q|(g(qLc5hFhnPQ6veJqDfM4X2*lKcp6>T2MW z${33ua38?dlCh3|%_|0zk3~fCHg?7mB`=#PQ7dK-5z7x}8uFo7t^cIi*f;asP-Y4-A0iEGT<7x(>(kBIZ7eUh7&f;HBA`&se==mnNv8_0U|@243){P2~m z{rTnc42?uIo8?K!@SGooQH35MwKb;?*~ST`>BRniNArPjc$1plU|&Z4TShQ{?s@Ae zkn+tPDM*-4&mT*5hB)hQ)b7m!y#TfUI%zZb`Pq3A{VR1YzbOwW$oEv1kCc8T9#@%+ z6!;GWT=boc?tVv}e?RtM?a+xoi)80LJ9IKOG|Jx{sr25pyrF~kO$z@n0U?Dk*67@K zbSn7^5NpP%#>oZ&gzGHTnmRcT2oaR}rT`5@ zGpXW&*t!1{fA)IPO}vc7CKsP4d5Kg&tGrd>6rl09>~Ys-vPMkl4#V5oaqd?(SCh6I zTSkQSde_6_R7d{90Awql^G-vQRBjW39(W6Bi2KpU9u`CX=XT#q0-7QfXWP0cBy+jH z&+)5z&YihwZB7socv40zS|%p0wUR@>yyZ+Gz3XGrz|lT&y(4=yZ^EViK*2fk_rzIk zcl9Y(RQirMW`q~CQ~l8h{cnch3Tx17aJWBij*tvhWCFL$zqh6=IauY5CmL&^;J+8+ zYyirrZleg-ASYuOqZ>4cJ!0(^RBIqt+S{cfdX@KN1^#5ob>$dfC*&ocXPHgZGyU+P zIhP0f8|T)=)7?3fz~re0Vly7W>j< z+94VC>5GSO3-Q6X&3_~_yhfBAR=NjzkQ}VMn2)XDaxbD@(9m8NA^U}~l8k3B%=XK} zCQQc=F0as7ZoPDt_a#+TT9Wma6VxIj@mkvG-?%=HBA7kuzOb}ax0<{rlE>27%Xi~8;BZ_ow8<;*0bHTJZ_&rWgQBH3>{y>x=f_jb_v%(<}z>6K#mwxzWKHtF~ zeqUHTTqAinpZ`qzFB7Sc;>L&FK;Yh!Q|LT+zbT7#iTY2o098d(0SQoHATm9~vEefn zz)X_q{5@)4e-+B(G{Ee}HoCUQ*O}ziwC5-33;i8AhqD*c5XH-OMnSTilU4mu6oqOV zp0tb%pI^bkZt@4Tqn~Aeb(6HDkIoV|T=?_6>y%r#pk#Cyo%<@0}w4DP+UH z7|0j#+)+u+r&&km21xCukL6dez&a%dk+<$y*!S8~{a3gITlw-uD;_0sDanBX2CcUw?dEA&c-A2NmZiwG=^nwD=!Y>VEWJ=$FeFYMx z9^lx|H#R?Ym-agKOX%w)m5*)YSCYn_UZU3K@42YI`!P?`dFO zp*Y(+JGTlI8le6+E8VLn{;BvS+;{5cEk$!;xce)8dEQfPH94;V1@%Q*s+7SPtZCv& zp@R@V4W-lSgpYK;YhbJv-obNR4l!9tTbOV)CWp~P-ul;V@!}I>@ z!MM%;%a4TT#+fRHCDJlQ$iqPz4=9vy9BUJjV*bgp^wa}T)mpaajU|Tky9WJ(O>66Rt+l zMj$^j{spzCP%Jhs_<}{pW6?jbF|HdA zT7MokkOwK`7fwQiy=;p94V_6^)YKnDHvI?kOik|j%N2DV9430Xvcyuj3|Nh80}ir; z9`)BpdBVbnG#L2LkKT{<26JBK_C15)5k-`s0_EwZWsYwXMzLYh%bHYQ^_KvdZy4}e zGM`s#97&y@m?|TwZoeEfdCfB!ketG8&I~KqL}N3m6U$DyleYhtS34uU9QjC|h}MJp zbP8(0E%^U6&lEyF50~`k_V7}jnMDZ80F5M>&pWFxruydWGwDB=8$6I~D}2Is0)U(5 zW7qIFIOj01$g)YvS>Dip&k^9s(t^RvNjoCQER84aQ4g;y7%Ml958}u|E#aB-+dmwDXAr6 zJFJukg_p}4VM}DZELcN}X>NS~b)$$o^m7`Ac)&sDka#l!8t<=5N3#g-?HfMr)L=vI zmZ|&IMj-X<8W7Aqcl zh*}Fuc?(n2zu4zYgNQ%*aAi$m_8^x6-yETrjALdI`VTGufPifW9vW)ijY*B>!FaQi2%mox>j#P`nwxfUy*WuOxH{sT#7 zUr#PB(2u>q1#GCXSoIR80s{EkTFWb&ad-I0EmfnC_Wv7wo9Vwi!&h~stj=$YQ z63XM*+DUxco3)m15MOU`B*ULk!S~0rkp!BUBtpV7w4^e4QMZ3jeSO+!@(EV8C}@~t zDO%gtQJ(GE9%-V}qQ?~SA4uwCUC+!aJ3oP*0Ujub#cSN=*$gF-75|vtLR$U?|3e#y z3`8}b^pYs12@Gj5JaE|Df`ee%ElktB}SS) z_4Zz$Hj=bF`mV-z5|F3qzI8`e)YM5f3A4WZiOT<*$U{>;wcHl-f`XNQ4CsAXU7>+# zfA*(vhTbQNYl9j0;#iesGE%QlEKl@1hg$X{T^AovaF{N%%DU>K(Mke3IbpGG=7a_3 zch^)Q<^O@oS#Y-gpc6lu1`7MFH6S*|DB}{c^gL8%)BL=4AphVYYsw8m{kcrgo?n^(QGPHqMA|V9qE%$~t0e9B@T8|tT#qm&t6*bgWHoFiGkAUU+|BbQ_>9v- z`CT%dx`z;_DnY700VCyHt;$(DEZ_>^Wn4P+ZSYWjQsdD+kq|yo$oW+Ej7){9Z*hAs<0QaEgt2q z_P#t{LmA0|6i;D4l4VzH0ocoTjGVKcRA*1wQYSHNxpS_&wLx) z5L+lI6gw}o{-ubWHkgrJe|#J6 z?wnBd+nEf@Qm&HPJHrNt)!8dj4sJ018&zN{AiD%y7>05D=2?{wj%APemQcgs6_~I< zy&SvdATNhoUaS3n+^&jEScI_3e;^ICnA2sey9;Xudx!qN{ot;qsRfw%+SSNyK$n<^ z^htme!@ygGZG*0ht_H?Ke{NYr>w5??S2ui_pjP*0rb~Qb#k+$(irlYxn5P&m2!-E) zljp7kJm~a}kz>D5!T6q31|FI4Veh^;xuO4vcj*`C^VN>bkjJEd*Pr8jkH9q|F58lA zuvaO?YTr{z{h!(-sAM`4RjMNpo1uQPep?d?S+%`ON^4=pWgF%}#J^v`9!Z)D_n0V) zzq`t}72|G<2G2nOW;^aXnz2_pqHFQ*`3cDe^vrY-t}UpbpXz&pZAg>+Dv&ZRzH%Wl z_pn_4S&z(Ah)k*5LF$Y%u2$gvn|yjNsxMQ>yd2KDQg{^yJWIA&BIKCL-_!ou!PJ`k za>JK-qiAeuB+ReIk}xd#bOndmnPcs!_T1DL9l*Y;tZ6Z0Ld{+%OlKW>h(-mBtDU=y zNz;Wgoqr>n`P7*6II?hYG9W6G)Bo#+#D2BjYrKJ%XY8q2MAhIxxSqdd?-Lu@8nDxx zX+jGh5=V3M{ze-(U%X$A)b7`5!cB4iyzJ|~6US!S0sXIW$r%-5kqsOX{{#6E1ROo{ z<>Zt5?cU|1&IFN4EWE9Fv0uf)7>cHDfT9OMolW7(FKtg5PkfPh&C^D}hlon4M$C3| z5;e%vKVbI2rDF|N=TTDqXy5)F;0KN4k+YVp8_##&F>KJ{k;}Fw)e9=+A0xl`=&lmo zLEJA@?fU`(fY_^3^gvhu-Zxdo!xsiM;z)1r+D^ieO58>9EZ9;{`=?Ttst1&71x1o8 zy+Dw!c=bzYp)ZoOhv-rwQA35o*nnAecx^RH?V0e=;GcvchA_Z~Jj((ZMN8wJ#Fz-1 zKM$S4=EFqW zKJQz%^xm3k2MK{IXx9}p|FG^0tMMr?w+FoaNS!)5LYQQwB)hg}(?=s)c7SlWt2cj% z%Ef{ivgnfjI`aEOL_C-@1~Ngd$|Sd?Z+Pmh?A-G+r15WJyT8q_%L!%-w`B4hh-O)I z4t)8x*%uXhr=Cgss4SRHbUtG!w%RD72_NYx2l}C-R2-JdSK9q?7Fd$|u!7_jZ2S_# z>c7ABJ8VGLhrhg)b4mUv&s&VYs!eSPoV>YBt4NIEV~`nZy!(Tnc~Xqu#{W>MSaG&-@5pIV^?efqU2k7VqNQ1#H7y=mC zDP~cSuukpir4B2ZhaC&pnornjly(s{*L}B_t~!5dNMtjv)%goeY8AdUXk_#wDgJ-hGaK_h@{2; z*K3{M2Y$baE-qmXuI>c!&wk7bXJ}*gD>$O>n?8O;PCS}9T&wr+s6Xu$a1>zC9B{j^ zO^@i=HMkD;JN^CM ztz%5nTeC@LaY>GKG3u!TsfpYgZr~y`89FVg(jbJ)Efh+Swugw=rQTJWGfFVN|G3Us zs7qL5Q^-?)FY(fThApfXdgy3znbr0mNc;URS9T}yyDtoRsc%~UDv71()JprRX-x4CWS~zJOf$WoLuZAcThgMhEoAjgNe@>)Valw1U5IK zE^jKqb2~361^UCuu+$r_v6oExgtB5Z+PB-1&T)K9HfixWWCG3fzF`iVc$jUqV1=lh z{j~>2+)2^LMqIX`JC1D;vuwBbFb!|?j#*FEKHL4M97heaM-Q;<%pGFt4Q`G(DhGHW z>W82cI?z%|_T}Cy(vZY8X`b+pQsNs=8FEf*TpTrLXo)kKe%(1SD+}dGlF~R`z{3or zX3u>OUXZdQIcptZbax;uK*!p{DZX8nX`BU+aH9v zWr5F+!6=nJR9rKsV)rUE2R-7|5tq$`FT^Hfltd5^naO_Z)$8n^`PBC%Byid(Dmw?$ zFv{Y8lFj6*=SkaNYcVeu_Qbv|bpxu;95;AkJp9cPqL!TMsI+`d|4O8L7SS%p&H9%^ z+~u@9%s<9Y)BfYt9`ukoC3!1Hmy%}*C#V$q)_Dp)^jMSy@{UxSaaZ|NlVCOa)!V2>m z5nko3gVi7PzbWH&Y@=976xzBimnuD84(nT;z{2?s{}_bPneu_GS{+IEDq4l+UQvbo zf@=*iERz-a|D_fu>G~_L`{O@xGlMBosCsX|Y;`%mMvEef5cNEXVo>%pN!aOACIRa8q85!gW`RQ_8M({UO zO)B}oO;>1`rMkuc23ivcVG=^C)GW_oRv7(rwTT-r`Tp~7sm9oUStPo;^A4QN&+qKL zqM#u|U5^j1vBWOVfo#ibf%o|JqMfj+!^-6Z7f=Why)TFgBI4C*AeXa$PZ$Cp@5&;gn2u}1_A5C^Knj=*{a4=A)kpLCZd4R;w6Bzvue6shLtGuCeF1Gf6#O3R|k{1dnze{qJ3 zyzKL%6D<0cpn_aF+%iHVMyYk4;?2}>-FiEND8fp|+nIPhnEFY zr<>Y0HN)U1lP~Erar2yBt-ggYD@DC{&9LTj@)?=^{_)^Df31(y)@k-%bq`uMUXdx) zCMW-VUC5Cj&`FB*{#XS1=OOubC}5-kb!SHZ$k&s?dPR&LsJh+^sQbzrt2sQP=BU%W zB61$PG3i^efOMB9;U;qo%fvo?u-rp8pnK5@{Og)g3(I`(;(Pkq#o|#ILgHi=z}YuJ z47bD%sml?!+Og+L)H(93AsoN_>h*#jj{dd(-N->+xA-uoWdSj2)h^reG*kqRX1tK| zFlb8+YC)Nf%>eCQG2FZQ>F@O|I1^%;nRwm@uZMY`T*9o^ze_4VH~LlT2A*z+^1YO5!wUoQ*LfpcpDRV(Uf%a)CQwKpy9?zeKM(#i3CLp|h1J6J zJ~#-zduR^>eahWsVOBknSLxN2xFK-!)qy3tCe!_P)HEEDOr{TSq=7FWg>U8w{m>s3 zbg;IXADAP9H=PH-=zzo?X|2PpBkG)uSy>SDd36gjm=4T0w#!8iy0hokwPe39e7IuGrA`_A$P&C@9oJ>$`W|?w6S)1xO zT|y`~RicgAt()P~H=hp0>2hyXl>rA1tBoeVXW@nc-i}Y~sh@cIF1iHoz#MSW)(w(= zd^NKt8UZI{*sYx}NG|cw)iJ(owWB6>;UA%o=(3=;YNE-!nb3L1%PW5s6^A>S-hSe` zykvo852O$*5-t0`&vgjcwzd;2P;~xRo>^@A#CntRO0>pwXSSLau&6bXnSGY3fFI zU4dVKH*odZ-@ks0D&+RPg+u{UI?TFYX*o%*X81IZ^ErK4awv>OLM6gN8eRk4Ouy}* zNlsS%l$x^pOsrpeQb(%aN@z5j7&fU&aK@{Dp z>eh0`&7e07rO9gN8{sXpT}cR%Nl2om;dN!;<+UofAsusEBH^B#jYtG<`b)z<#Yt!g zGIscm_Of5Jg6TqZRTmJmv?mJ3=yAhe1P)!@?IdnG^#=Gs?2WonBfeKJyc>Q<$W=}j znFobHzY|xyTq>kOYdaS$BqW;eU)?XX9U1@j~oLI>8^4V0;3u|La>SRJ- zAYEu62`u2;9GSJRY?{)m5CYQRD~u0?6>>!k4oDaBo<1Hy=P~EhC+aQpEFAK@`dBEY zC(e|MLqm1by73gND?$EJzT*L|qhxH}6D2?*_D2Kq&KE?uz}LSIU0Sk0zWjeFr$G!b zSa-OC`cr1}+{yN+?wn}V>6F^9Ul3XX4Wj{Ys_6bwF5g{@!!msBZfM3KHicRmV~UOl zcKZCSE+M(8QzPI2+tP1fU!ZLt&h$l*XG!0ctgUEz{|l1vHM`)3j?UNdlV2mdW3l(V z+tN?ZrvnsnT$QP078HCrI%N$qznnYO!(K}YaHvS~LYv6lwVVm=X3P4W=hjYEMblF> z(GJQ(y8WGTbswoOKfS*Qgzeqk6HqG2A4UslYp;!R1!65C#S`diq(8`|PmCWh)@^rp z(v}=_2=y$w5*P+&kyeHKv0-{(TmgsT&(jB{%ss&0*#E{7bIiu$JsU!-1lQym@+&~A zp*oCI-O_vq-)OMA!2}<|MDDawFikeRWjC*z{*f*C*^Cc1=at~Enp8ce!mM*YRcpMI z>OD=q-tG~^l)(jTB-|$4&T<0bn31hMK7#CHzb`zc{G{+(gutRJ_j-Q`x$_@rH!1T^ z-Plh*ruC@>W*=XMG2MaV8?yu}z9VIpq{PI9PY4O(RADSFRX^vorReS`Yajb=my2QO z*3sE?e4Lm{<_|a2)o|wQZ{-=+BUa9p(Hq7SxlG@NJDsmL=saP)lcyj2|AzYvQ95%W znuXRo+C|$<=^dbBA;O#;rsMiALPYMgy^4TEJg(3b8Cm=QZn(V|Uxn0GJQ zQf62@3=zkz6l+8HeE@-euuEo;anO*`K~V4jTw2(M)dy7b-}hIovP-2cWHpQ_%pWB? z5NBI|8(;L;@y%L3qE`=?Quq}()IfDN&(~w<0bPa|viM+!7xPx|*zixZ_i^nBsnsB0 zsR^+Z%NrTXZ_K{&H-GdG$ShF)2%Gs+G3o1NO1jXgzN(s{-k$y5hwg;xNo_kmF^NLj z=iD-4Fg@0{EW$0)gk%9mgBtZeEZ|a;f(#A}efZ0A>Em}vLNJH6r~tHz>$Ha>MHBSyNhw5ufHJTap))P+Cr}+3b=uLx^lUS0P6|wa(}$mY9>-|sVxinV0n8dXbLJ1mSHQH{_rF=DRSbpDeGB#sjOwOP z81H@KYF$Y|{;kYq|M*IoXh8m0;$bw1aW95v>$lmZsxr&Vy=q;_m~+zQFO$@}RYx+O z2iO9%j;F#})`-t){=3jbx-g9k6L1QQWpFJ_{a;Dp^^5gfL*dabK$~F?GMzN?J&Qd z0;|=eJwX6$T3}O9T*`qiSj?j&GLmvtqx)b9htT=>D+%eJrM?-JkH4sb`1_KXkc#_@ z1QL#|xaqh8EqI||k$2ot6UyXhX<*S>Kb93QAgsHW01N|Z_6)?=7u%hw__e7FT@2Cx z9PHKwLHm?eGL}zw_pz;c3ajKlg2v@&gW8tk7Q>C4sXDkK49#=OJHFY~co}9l$_&F*Pk!;HwcShLCmr@qJd8YFJq9 zSR|9=DX>xdDHU~eO~MzS!$N_SV6!Ag7`>$cr34$fxB{50HVYwkDGY%S#PnSa%T%>lfQ@IdC(4GsqJl?h_k+*%h$9)oQS!H!6X>8 zom=1K4X>-BY7(vNd0K|+?YsAYY~9I0qBui0=)(Qiy;5wkwgQq``(LIg{&E1;X{`*( zbCXaZ-sZC>1ii2|{IY$kjlYE%fxID=yP;XJP^9v?+j1cQ_O5dgJhIE>ci5>4x*{jf z1qTQTnhy$vP%j#ae;K*b0aTR^>~>J9elQJ74>muvq3CSdJtmJ$%=TFUhMlud2|s%q z74mYS+@gn-cexZl#BcIyKdp?{?M^B0GX;@Q^z}K_HH4e9`Q>D(zMjwQYIwVdMR1%m z^3}&-lL~#Il@~M=eh$$QL-6Bd5V*Cs6x%TLH}T%&V5uAmVgAe*n&7SXTPP!CDhri1 zI*#CXmsMdE6DB>QNV?38CQj5JZh0Ay2V_K#L9#@mFP_iP9ja(#lWf77X*VwF1ZeO+l1x6jPTd85l;PyQ3$Aoi$!Sp!ZHP-8~3GFATC#4NGK~zN6xP+JE zF8P2eN(jJZn8#QrhV#puXQT)g2_|$s0v`1PZEhL(WpZ!onWE?-vnYY6z1~> z2E}Xe-n%(=8N{OXpjUe7!K%O*%TO6(SV|zG?pwbUB}bU*&XCG^aNGg1Dc zj=W`Z%U?|nn%}ZvE-DHB7{d~NX{DQBuqpHgpg>F65{bkU=={=BuQL_S)4RlpfazlO z`U%s$v@GV{X$7~%SN{3As+3p&t*i4P>1cM9DakY3I>NT^m)ysjFytkZJ(m;l<>3Du zmZ(t{&`RE(zn>^Rvc~H=<0(^`l6+w6gmmf*Z{lvOhqzr>O$-xpo>RGU|A8O_AiQta z*szK4!dA%bKeentJ2T??Z}ynpJXH~evLZB9;>Hik-hxT`UN}yJuO4a7{anHxB38uSV;c#$_2dY3Y+h)aO-^SN`R&*4M(kaaOkb zHbW=-$R(q#kWb}?XX46LEv+1h>nHvOoP;W0G z?9GJ}Z133Q@PYfyi}3vUy(BZH-c~j%(YCHQ{~L>9=9e6~f^VT7qZm%Nz3OeN;~f|& zMa*PXR*@aU$f)h(z5pOCFXUr+@ZKV~@?}0R?!uyu{CLJX`ZGtYLVR;OmtQtvB_;MH zh=>1KGKAtVk#4YBf`!i$Yr!pGK?qiXB7I z#13NKb}avH0QtpD{(p`DZjoLjERqB+9Wr~k8!i9Np@_cWVca(O3lI%|XOPq$2J!4$ z!;T4ChyRn199e~jAD1D54}cK9KUC@lhK||z*RQnB*&#cWx(|-A8L1k{>nb;CHWIU1|6#%c^^RN_e zTT1?KGd$=C?|(KhPco61_?VSW4Ey~MZK6~6pc&7m9W^Z+S6z1V-ThToFBM0|Bu6i< zr^JiD?5&5VWuUep$JNYr__%S;lJGCImf;WM`A5@6vGjJ#(a)4E)84;%h&p|fA9@9= zPco$|`FO?zjip!<@UA85?Ywr01TFxB^pqpJUd&vTv0^>jRr7&?Zm7nsUVG9PPZKL9@M|CIbbb&!bVinPWF>CXN)_PNC! zSfx>Pe%FO#9V)4`t&2_-NcyR=ku&|7F!0cMyQiZ;t7ALCTrn-A9}sTFVQ*_y!w%eo zq-nphv(QU87By+l&;c=7x6bDboG=ki67u`7w+EWYkhUd+gNp3!%IK21K(Cce}kl}VU)@C7pp-mMhRzgf|~<%lamx%o=T1ZF>AFbh}a-oQ|)w`4gu(0y0f zxsDMbIA5BnO|w+h|HFQyO;>2t z>}s7$=}u?&a18)B=cwFhsAG+ThB*Je50P^l!DW!0@+q>f+O1y z$T=t5AM1j7xMxf_!9TE@kPvX8#=rZ%{v*V5gev#6laKexaTsw(Hau&=*GmRpQOM{m z{)4vqAbXz}BC8_y1BC7QyUlKgN%Eh$A-h^5ZUGR~O3?-ALU_IsdlPC#AnZ>4AK?9; zBvSFyDp#)0AVOHODV9VKH!bjl+|@}zx1Zp$yAs*eBs>CeBCO5#xqduDi=OsX&vx(8 zA(L)QJFUldHt+XWSi&*(YGq8j)D%UVAOQQa3OI6N1z6|yo#^s-(VUf;CiX(DZ56K` zQGWo^88S+(8{(O&$8UK8Jb^8@u!)4@8ja8g;Y+%@kRXyp7Z!kq-apE3`0#RlG{*W} zQ73JXF`1q^e<4$WAkXT{CMn&VJeT?ZK(}gCMtV#8OPI0Y+wGp=23-p?eD~5uTziGT zjOR>H*-#&>E&hl_d)!o+bEfZ=JK2uqrHq%g{WqE#z4`&jM-tQB}Bd^`u9 zE&4_s4c;UHdVX=%@z~#{=)u%gU2OerIb|H! z(qb5-!T)Em*J6sIb^r5(=5S7>L}13#A&f=V*6aq-{8XPkz!RUH^H*c!ulv*_Pd;!s zsLV?vFW#+n;g8R(FjTvYv-Rq1SC)wwF4>$DLzZ2QtrkP@*S%Dy{{WDSWld@mHS9DH zemWg7Ra}S}gZPhvi%@gtdN|sfU%x)0`ZCH&!)@4ZLi)f&@C`=p#q2T)Ts)!cktKh( zrTcv{`8QP0s|&!>d`W5P$}~p3EKa93%E{p%VjVg=0x%GgSoqx;QWSF%nNKQ-lSmuU zY&wdi1$yrjjhJ6Wr!_Xba$ygGmcD64e@!^IwmmiJHCi9d8_P_+qa;l8JSfc+IcHXO zi0#>*hRJPfC5P3^6Q>WEu}vzAHgmHG*1v)*Cah*Wa9{sFSK_;5+euHrfcrHUf|^~= zhz#A5qU>n52!?&Xo;hH&AclXCHBFDn+g9M8&37_ElW4bHpVNf$tmB&25jTZ!X2;=o z{{!K=IzaPGuTN9j$|A8qKlbAYhb0}Ef|;wk;zJ<4;P8OB5zA7@q#LPfeC(u`(%9Fe zihXtUmH6^%>cVI|@q3}$0j~1#!2{eRrN563xv$|_J>+MmR}qyv)#q1FRV1My)XmLh zjIbHThpe2||3~H?(l$G4AqT@GGyLlwNuQnJS;=x*cU%>6O5s@iK7>h#rZ{A0`5^c7 zz$*Zm#cMdQ!b&fQgh2@pfxldW38`fc5-19) zK5i}(wAKa_7CjqHX)?4PsvrxHdFiyBh`}Y_Qg*)j4!MJ~Ee{M^gfJ!^YrWVcbjO2T zT;e=0yo@GMnVZ{TZ&FayE|;F-J#!_`qk9kN#AWjmWT zOS2U8BCpi`#-AK`1wcYQ-qq&hhkB^82eO38L{yRIa*Jr-cP2??Rp;_m+W%sIoWD}Q z2kz@W9@?gVK7Pmz_bhU8>V8@j(Zv1W;g`8f2_;e?c@xJp>Ebh%`u5fniWw#f?;_dH z2ovGK8ant+cW>Jam#kaXH@pU8U?3~L%Xcp`HSR{zO`FmLVR`*V^% zsC4c2$|^z~+~H+>BQV=};nH8Vf6az6=761viyBL4Mg<3wwE~fnby>f=!as%e-})Od zn~>?sMqz6wo(2()CdCgF?xjj$v)wFu&-DWU*<$+v<)1=*#?PZ(!8NTdm#_tdlJ9uK zfg$#xER}wJGRa=l^!z5kd3EhL)#t?>WPkDa4#d4?u%vJEJw&(1+y z2sA+Xus}bn1Jekl^0q%!X~TLY^rVpUhpNZmxV+;gRD$&Mu(v56+o{KU)ATmOR27iQ&DXK#{(wE zIZjjwzKG#O@vs?*z1FbyRMISY3CVzo;#Io3@#1a|yUDn?^rcf3jEHY;s(f{81p17|#pU4322qXkFC4D=bu5I#lQq3$ftndR;IGmuYd z>1=avzA;I&I6dh87S&eKHEpll9$OXeBBDpbXe3ho90h4kw0kTusy?ksV7)LXWR^(? zt)hUB*mo!)Or1AY{4KixwZk0)Y3aHo>6dj_jP~wuebsJ#3l>eyM6apnACoT=u_rcn z#7_1FK}_OE?XYvTCxq9fvwz?Ag7fb`PF4n?;#hgqG5eERj5cW*06SD z?p=TvavSC)BNgBT3ljW zFUy&%?5gi?@yt>XjJm~81<^sum;T;VmlvgOEx|#Vs>|hSutV=Blg;qsb)-*lOS_}@ zP~`dj@so8SmoHwWF=iU{5y?*-`BQ_BuxX&dF{>}W#x*#Iu`gM;al6uAK7(Uy4U0Z| zl62bo>Qh42yu5cp59zP!8J54}YZm<4g3_DAlf|9(t?fXw;MSNS{y%fdpQ3s3-<)!Lh{4r!t#y@89q=il}L#P@y8m|DrO@3yZY9ldlRQJaz20%HEp z!II1y5VYEmK_5Dcz-&pdph#QiJ(##T@TNvDI9&H$^*J^D#9&E!YDFwIB*I&ht3mo* zi$SuEqB1*{nCp{~Z>jcS(k4S}jd0){Q8Ud=qa-pcS!&tFujg`I=kQL|U9}|En`ZeT3;$y(dhif3Y7MwPV;e{7P zgYhJE9>$=^wz*cwx1_~ME1vQvtdQi#cXMy9@nVM47pq^d7-M&Q_N^d=_`k;m?=<8c zpSk308@^5GdVW3~-+N+}T*e~rR%9eKqNhxRsS0HD&LZ=)UX62Eh=&dL{cA1pS10if zX~PzPAJd+_LYegKG0`v^JFZI~i(N^`&H)a<{Qkataf#2UVg$e8(9zciluEZt4va8H z>(9ebuqJR>?V`;C3R!ncGVe3mNPEVn4Qb;zWZ2+ziZ^VwKaKbw$nZ3_7%8gGS{mZ* z&&xlPuK(@{Fa^J}W>UVY6*v|-m08tSn(+l6YdDmrJ0y^gUF{rBd!COW_bFkU@rTqb z-`T?+IHX#BXTq+cDV69(qqP46y&zqAw17O|xLCaKKV?|@&eb$JI(qive3J|I^9QtU z0>9}}vXMZR#ZdNt733%${r-u5;c|T$vdW9NGOV;uWr}>NeRfJ?>`V-1K_z{sM0i(2qSd5WcJhy zTLLv_So6)jlAj$EdKr_^9G<-=)5e1)qVBqINO>oZtB}sMH8%r_e2+qRAf{P7yYtDD z980Nuke#THP|EfMVCUtl{>j}}sVFA~2KLwJ&UXnW*ndjzSDQqhGc2$9Wcs0cR(#=O zB4l4y$YAgscImOpoPMOVgJZEZ%va0dc&02=cOt@jD#rNra+Dweqg~WWpt~nZB$S25O$UnN0q0l&Y4mEe_^)p8 zM`8O;FMzuW1U6nLWwNq!b}D$mB$5*&5tF}f&AH$NQASp)FmVx)DK z7p5-%ALx!6f<3_L6I72%t0d?p0=VdY`$-ibVCm9aMo6Xu((R9MJ?5ZNCcZ-9R|S*h zK?(FPXSgXb-cWxtI0x}u`fEsi0PGaSC1Y4T=dL&K-rd+H1QQcGUbKl_&`B#cV~z9bie+^J}>5-V)h;X z1P%3j$PxCY-6rl5)Vis)fBJ7sTiQkyUYY+Sjf$H>C^T4O3HfH9sLd6&*1?J7O|+X6 zNBh$CrMz0!wMc6}6zZLLF7W)P*H|`=$9r{%b0{ucc`xN2W=y(nh4UjJacADYg;$OC z-&k&{oMQ7s8F*aye2}!vkurC4S;smj$kUV2f8_C~b(9!l^*F?8>#{|i#nO6IQJlT& zU87ud<-)*~zfAmpppxuy6Yht>6e7(TcJo|(Y52CM2#Xp?;Zeui873C2H-x^?|5~s> zwGyVy_u)8}HDyxkVv?t8f@Un(ZBXkjthnTfPo{aiP>0Y!8TX(a=$JMJltqbDf?U&*Ng;RoLkUcWtHn*tkI&(?JE=>Qzsf z1RmJa4-D+VW?Y}cW)ZbMMm-8*{h5w4Nlu_Z&-xls&-L{Z#U}4#eJP}J&^QPh5La$2 z1Jfk=tB^Whieb&_cia8b4jVb1-hq8Ry|-Yo#`aF0q=?cE5BB~sv@Z5hQKx#1;;5su8{Ei~QJ>%81Rd!* z9wYDWhY<~i0qm=yt*g3&UK_QVi4XxN=oqhpExWig*(Ph(z4v{X{;_*f_!vGeWqP46 zub%u~!I0BIbvpa5w5`%Zw>&16)^tWlE%xp1Ncd{(Uj5Qf)gv}4kCQur=tTEIjx)zl z;=$uE{}$=IT4_esL$?D>Ef zYCYs*t~3)4p8?%oUmJz!4;yzWE-Zh8c^AlXoCkGm<(TjG|15O5bije=pIYB1YCUF| z5Mw30ir_`4bcp2JPDISvlP+^p#wvWY)M{tB@fN5=zGK=WtHpleddaUN#+$kUb;#q_ zo&6~h_%@Mxa0eEZ4lFWh)o^Qx>YQlB+}q@V*?&8Z+J0FUGOg~>2GuywYkRmV(KkzCW=Tm9c2; z;GPZ{j%q5JwZAaZ3$6!u^b=#lf5oNoBwMrt>giAcX`55RCN!FhcE7}%;%9!gynuE4 zxwV6qImSDie$q0W7o}I^Kpvv18VX#Mo-eF^v`FW9xffdB%d@mNZ9bYte9T@NcVE=W zQ@{Q@Fg=^d2EbXSJ5Qi=LniZ-Q1mUDx-n!-Cg7)Zix`Cb#&DaZ%-3;kdp9Wr08v zl+qA)J2u-1@OPy%LpiQuOkG@>6LsgNNhjz^;^s*s@5mgzTCG>4wZ7cI&q8hnVfwho zH>qt*VkyBik5|2J0>{i-{x;tEN>0W*Z~1j=r^^BoMz8c~!^5i?v7lPeE3%i!p0fFZ zLu^X{4hq-u7%9i?M?)OMvBKxm3gOk3o0&0V{3p}7f*@@jXDYOAxa-??ArXR7@L2sW zS?%&)?6)GD;E^G>RZ!j*nW5?t2X-!nVf(T|S^?o6pqEDWwn>++4Y!0ikLlQA!P&Rz zHwi?*tw}t$+E-yZEWCbQW(EHJ*4c~JRrVYiP#Ur=U@tnB$L^mR;VlBp*nGmI`jdNd zlx5nkB-H(etGX@tS?ZG$2P^ovr<2%`Px$D1>T@R7(8Bmzz}xei_rU=>-;ZQ^_^R% zY?|dt7HxCRJ40v;-d0^B8$?r<5Bf3(RL+qsT;2{|{iVGM$=&%;0(=$}rye@ByTm0s zdJ)8(-|G=kJe$Tkrc~bpWpy|;GxkSbcvDl7-3gNgv2t22*V_A8|3lWOa@VwVGYqc6 zxTkpEOf@Qbpu%qQhESeOLu24SxM7hZNZE~9oQ@7~Lxz;jiH?av)>1lcsk4E$a=_{a zS{y|Ln?G|@mjX>YI-c{t}n@BN+Y~-%2r&3n#uw#tOeoN)>>so-X}wX%SjDSVqIm^O0MUm1MY6<{2NQ zcDcXcitmQUaX+wDfu#e!Zs77V-=?IX1x4)0Ladb~im@>d%3_+rehz|%x;Eyq;D-tHC}Xzg@*8N1;c zlT|7I0b|%auk`^>xqt#bt<0$CnM)O9yiqxH9QdG3bCiiQ1eG+3%hL_-r6yaQT-FH2bX1zhM+uum=+)Vd z$yPh4zQ3gE{fjMUzagHVOO=^&9}E$yBV7!WsV6@v!aHguYDsdij$v+N7}aaO45lqw z7(nFKQZ30=k^Hx%K7J9+YD-<}+iGl?)>5(KGNYWLxEZLahKu%m<-CFPi-2b-d%O@W z#=LAj- z8X;UfYc$TY=nE*=4bv6WUP)#0V*j`PZL|rD-;{fI*;O4R6{CDfCBvL*%M%Rwi1_ts zG;duecu>ps$$`YrOpXgL-9-|BPz!e#VZQw-Pfngo0e4g)cAhd+wpH5%2qI$1xMNNa zehQKThu%I(`+E<`Tla2uL*!O*?-WI~^(dXA&05g4t$iv`$KV5OIdP*o5hp6dl+|3G zsr~Z0YdY8|wF5S*bD36_^3`ySa~Zw^^GuPBfDGue$m*?)7xQnd_8U*Tf(_gsv;`&rAt}%mE5k}GH&{ZI$W>NuPF9unxcAT4Y#{3{yd^wQejilhi1_$-JH00 zFXXyg0va32lm@^+(0@B!i#cR@b0qWgIrTAV`m(8{RgI_CiByw=WBX^NoLsn)2nF95 zMd3g<(afyoGFN|t8s-1*m|iJzcj4F4L-$uMj?d8GJ@?oand5ayojP;pp@MMIx;$nCDC(0%@H%Jvg( zI{ef?P?5V@M;2{rq#`pT$^JXwPn+sQJ`UX|#s|bZvGc=~Hbeh`%y{Bi!&NRNRMOlN z-Y)xUJu3eXl#kt%%RLRLVskbSY&%(F5N+Lk#{_eeHN%TAVaBLi8-r=<@tc55%{&=j zGTxLO5q;mLmrV$P-tvNs%&=I|dhpy;d7ty(%PPEj=Ij zhPt=my+^L3I^1;OhHR-X@#NV;a|;wePL`WNXf&SCPYKm~bGz#SBMloFpf8QVewg%3 zC;OlZk|||Bu?I2i{=-&{-#7n`y)%W&3XgN*Rq(L8m%zTdK?mOSb!uWOI*ukuC&bFk z-E$`GA0XRy@q;j zX~z+eTHZd$goFmYxJPL7dbu$`93-gBC8bd)tc*!Fva)cow0)ft{au7|{_SwW{?4(C z8Mvm)5omHMjKs-!ONG)%)ai}1w>9QPb6<`}wL%oAH76%cpbtJ;9WDWpKSh5i?Og`R zF#T|-JO^KY2V{kgyjpk_Mr*^mXKq@=eiGg@uv9&Oy!~}zO)M(g@}dkkvuNqQVp)X! zo?Gc-+MrGg-;25kQ5Ha<$bU0^+FSgQWV7>az*G%E5X6!he9^>o)SLX$x&b=OaUj5n)N%yPhg|=I3@bu2x89+s=M!+RLlZ_MU3qBcD%sOU?c&{CBfm#!y~~$yO8Fg zOrl7FhBa(-6!jBdahGIO%T_VQC4=JpNarIm1pG|Ygh{=^WJC$jy2rURzMe&Zzn>|! z+2oGl-@3R+sDeXORIvFN;m4LqrBNqMG;bC?e*Gz)H)`Ue^Hh2zSNx6_h_}w7?1y*A%Ne$Nr*A&@y?RfP(dfncT1*@*7#PyR zcG@JZPR3KRdn3R8%9*eOpnf+GK7=?(tG)A0euJB56JBG89$YbQh1}YJPqG{&mi809dOq_Czjg3 zRAdhj@s@43_ko4W-UNe^(!k3?#5+oCmm|>ItK)m&vL;kQ;<-I2n2B5{e>m7Q$0$f# zSbFL`+2u`O#J2z9Kyh^>!OITF3v+mde*M-hq1nint(*u1a918@?gl>WcpJ8GE}IVQ zww^>bU7D*Nf;7ae1&Z_H&b+loD0!(G`;2G1!BPXgoz2@U@&j_Pc^AbyI z3rJKt(`xERlNh#gU$86M(_>(0=K=LYzidf<$HI)S=sZ+1O&FD+i!<$Gy-)dn@w4>f zt|?g{RetYO!*%QdlI{%6cT9yIOg{)a6=vYg^LxPX<# zrsOQwGT-}yL|f8~@mu47OntN-hzN|RaoNy%)N4ueeJ$qM7d?c`1OUoUUiE*kF+33! zUt9<>*w49h0Iy}atxUB$x5L*bU*7()F5Lu1cXnk{LOk*JzSHM*?I5+Q%t6XZ%1ZGV zmPD0lvcK3x6greK>5d51AdW(5C?6|Z%#Dnjj?FGSFi_O#;<|7kg7#z)a|;`*+bzsm zu7Bk64wBjr;0gN~2VoaQ-~+UEc76~a|MFogIRiie8W$W%nlc2F9~aZg-rZ+c=8jO{ zQ~I}_`AtDQ{OwRUsh;}&Wn?#bF11z(k+BH9*ri5joqim3{MM~TWW5Vbf#dDqd z6zYez)>dZ$Q-Ph0Q%89?vR7*VpCe&fGf{urg)vP9W-~tGbFj<1`upv z(8b`peNQA0$wMO!Ij~EXeRO0}{{ckeP~Cc80e}AE!{Fc~tSYuR7xmD^Syjqi?3?4r zoJ(#CGlpPpxUo>AIggp+FYYFBY3m9M+-gm$5rwgE#io6;>Y&?`ga2)<0oLlI``%50 z%Q?wMene8#E)4NXFO3l%4v`OW#Dvzi*Mt8E$c02OCwkvR%O$~~Amy37GztQCM`RGo)V09Zp{4AMxEA@xyty~)Z8S2z8<60u_-vq&B^2@d*@hQfRHGRg)Y zUP{RR8ZoAzb$oG$n{#g+a4}zx5%^3rlLio~VI}%wfqy;v5*8|;@j<;Gk>ON6Bcr1w zMbf{rC3;yzQ=laEQ{;~gq4~z91&fZOEs^=`YZg6bq2=VEYk$3bY*hITPpD%My5c~0 zBz1^t7|rICOyp#)GfYn`UP3I7j-4C3`J8AKfy=V_tbnb7lIqQMuf4uf6`9Zv$?5?Q zD9@gGDzK8Lyhp|{4(qm?QYw9174k_60!cQbSYOM^9Lh8fAYYE=wUZb`NZL7oTrnKF zA^tK+GnFx`^jUjc85lj6`QTv-d?!2MPb+!sK^3&DYu)#ACWzVC(^qrTUn(w0kj1?H zsSERtZ}Z;WTK4O6+W2_gmMOsxwlo>7bD1H%X4YnV*S5ofY2p2V09_h%*ohr{FP(%I zR*g0U30&CC`$tbt-!DKu$(9TEUQBr@L&+0Y;<#ulEB6mO49;yNWtc>hqNJ(Zc2AuV z4(=XLeK6`^CIew(dxNP}5S)Dr4x{`8{qpcEuDm{OJ`Kzq4J1rFgqZ?KZ5N$Kbfsc4l78D=98qkI<<~aC;Kitru0W8t+ zyE#JCLaG_)@e|t6SD{<&11YrD%5Ect4?CsmK+KdpWrwXbB5b@V)&%-D@0np+Feu}j zU+9Nn3~Y<9+bxUuBs6N8{uV$;zT8nRrKX)F#hVh)ZIjgHHKP3L-_k}b_nW-4LTGE7QH@>UJd8Zt&o7O7lLC>hJ0@ch;m zTWaCo$k~WFl`#tVAp1nF|-N=5fk&7c;-hw_L!%ZdhoKxIjno+SsS)y zQmyd@ZLsjKYg+^r$07{Kt39ey7|`Cx*j7WtwBp;|1L?QQtDY)_O8kf*g>AhE4Waxd z#Oi$7_?NPplA(1Pxhc69nLH69bhxzx8(SaQmH#t(_DUVQZobTrMM%lep7ctOq9s-PV_#;wyY~5`wkgPYkzg;oo}Q1TFK6P9)F7UmTAD3rNV2T#K*3p@g5Jh{q$+?ZcL#n zljoId+u^o^WPFAboG71M(AfHn4FA02K((!q(T57n3s>01b6$Hd+jRFtvTJJ?4NYcC zQ8cfDcrpc>+@AhVMWxXwzQNlEL@@KqtOSHc|2fZzZ6GM55B!K5CGams7|T#0j~Lv$ zt@^#71pk{F6WN)067T!V`e&hmEv60UnCP{n-UsykW&BA5CmjCGcV<1Ih~pG5UK&2R zgy3y$W!^x8Jk;7hxKFcr%?MY?Jkn2iVBx}|=Eidlxe*r;VWo4eqFk8w?w%wN6xMEG z{`-1tAR41<(0RP5M_R^5(hhq)ju<>rXP(IAR@`AvEf|VUZZ1!U!EWGx-VPVe#GTgl z2@9&&SIEDC_4KE|{{{PSdd8v{$|(}F`cyTSHNw};KJDrepM*qM@t?u}Kr)>aA$M== z9T#{|OWzdbJS+yYk4 zld5<5zd<>A2}bu`U`xSzoC7*%&AH)f0^fprfHgawugIf%tx5E5#3WPu$3y0MCm3lT zAum~MIk~k)X+&REZ?L(oxb-9Akp1r)-F;M&;$_S1Di8uS${`cGXwwLy32P@FP9gGX9R0w zXpNJwbS}ZZs{6uQcl2xlS%*L1I~p7}lgJfgLce7beX>|Xn=mo)a|br*v)*Ru9ZU6R zA*g!LT~(1v(|>Qa^>JS9*|cXiiS!qGU%te*@3RxTS(CjxEUxMKXqQ@_F zwZzAO*97DO5B>u@WItekkP~A8l{vY_q;HEfB~@)A!rHZxwqS|@6U{?&QZDGNiM)Xe z<{$|bTH=>J&I>OhXCyaIz(3%YMlS18SS-brc^0X22ljp}v4RpKA|7rj;nYSwnNq^E z&Cm=8ur2|QL9e8+5vym;eZKE6g%^y(>Hc)E1J)$ygn4JSh)c#pAF<&9vZ_BkNy4!ofVd4d0$zef_^~ia%fQ*?p4J zWqfJZk<33lUHxa+kINY8TD8-^!eE776qXA+UdlMJA)qqz>@<^>1U>hxfiUnq`~~UK zdv`<+|8K`P-#PXe0wr40t``?)sHsltzUY0N@c*hucfGUCVF>^nrNg|tSOV43k|Bod z>!B%NXJq4k1&f$(s48o?332~BV^^H8>}3h*=nKkV&kpR|`Uh7T>5h5pv;g~OlKkt! zlX9Wu5Ee1s50l2Pv)K1sqgs3J+ZOUUq2BT)p6)jBS@dT#| zt(Ln`fiRD?G$>;Xvkq|J?GjY1^1%n{EfI&4*X-D>>5C|4u>;a!;p0Pu-!X(Bi`&CmF*-%_9k11$T;?PYzc>u%HA{k*maWZtV6aU*}Q+R&mZvn z{tFJy{k-qTy$vb@6Sn}0G8KF7dbo_j7qexa@7=>jiRX--(N)WEm)z}> zQ>e4LzUp2-qao{r&hp$%2@umKPle^Cx{cV6<+-x{Ws>8%O#?YK#qiMaj7Gjx_kL}> z0rSP)esbKHB-F_DLQL(-5LgE_?hA^XH1bd8IH`vkiqr&$QIl|yQCtJSUckCXUqUzC zo}BKGOPfm}jOglMVqKlbq$GNj_jbun=+w#DkwS*kJ zFI&AX<7_;o^Fam%aG9I+Jl_ zG|i!Silc>J%eVw_hcE>Eh`wou`*@!((0KQeAr^X+cuha9xcBQZRNd&P$6wyjF#^fr zNo|Q?e=cj#tGHJDhRa3f0K;TvTy@>Cz2W`$#hFeGc z%m#CkO^gWAX-yMCM_MAr<-6{d;%5-J%rio`=_ITTWPojcGVY%;D_QQTVP;2YWBm(B z4j#6>uhA}CY2vz%=Md6za>kkC>8?cFtQNCmLLgf2;JstHUc$A9*wdMiaIY^@Tv!<| ziyYCVPn5BX5iP8)>WhiW+?zTndJo}Zzfns+y zp-BdDeVwVc*NMvMSuD9T8ouWT0^7!9T&I}kior%J{!;$j){@i zQu8{d9D_alzorq)C!8cm$jRV-gVAjnyyi{Q71-B7&C3PoXMMtXn40*MmnA(;L#lzu z+gSM)SV55cV=0ZG&+tu-gUu|?nC|x}F8_)&^ox1ut?~pBJYG^SUoQ2(e=R7dhajHF zK9--|588uu=evpqzX;j--X^YNZZF%gu>72SgWpnDAYV$t=k1|BClb|-fO@%d=jeS* zw^<0l*CG9DwHFyQi&4|9`x2e#%I5TWd0E}pGnt(CQI>1a`Ebn$&dfS)SNa=PGG-I& zBolh3+>xaJK&^y*an*8#!^M?aoTRO zKuZW8tES*pWf7|sTHgyVl~?dkh)@#Ur;cB*tE4}9Ph8**!$WwIeDRU#=3=Yz1TU=w zmB4R^4}h)%b@AhL5j`r&@z54$N%*76<42XB>1p#Rq~@Ug!-TC-ta*&C_@2Ic#Fhaq z3V+oR-*whSQql&@tkMGSWf)1b^wZ@1N9Gd^)dVuRDDEE3#As$_{cY}(C$9_jvS9B! zKb1qR(N%Z`8yVn93a=jH9rfAf1GB=P8A`iPC0JIVeJPMr-fwYj_nf3AR{Pl_9}?HX zSw>(DFUzZ+3HW=MJ0E{MA6d}<&8V^+Ml-IntBwg{Qzz!q>P-6DksZv7#J}e`0~2zS zO(@33hfK1IK25=^J(R_JKZuY_Y4n$%bq-R^J=QeoN(d_NJBa)0gq;DJN;;&2`r`bhccwA z)K^`%ljxpPiOMP6Ac;F}Ia%-A!&nRWE(#(TMGlS(Vz13y8_l?uc5-_q>e>krxbG7D zKI&^$X7nGtH}q11`+gawP8jigdD7oUQIw0m^LBzIP#2#iuW0Z(*^cxoWGO9(5j2PF z{dv;Ilb5@otQ~|Q`v`=1d||IQp;hXd1tt$q=&2?Jmc%MYtIpW_qOu2E*InC;x4(`& zrORwx+}3j33G){XyxwaFznHABC~>cYM!##$k%uOb$sYN1!Cy>#=YRYq7ZLC6HFS*A z0i09h<*zW>lf&cVJN#13!c8yP@X)fZAh2f{RBaBSzgfjbk}c|LU@{@<(@whW8%E>n zNmWVM|4gn>0TnCnm&3EpPK=+W(}*gWBu6W}BeYIhZa=lMU{8`)dMzk&>Xg9HA!HA` zP{jx>yt;LlDjJ()gbIG0W=PSFfs=vv&QP;;5FRc?Be-AOBay6&?=}Eu7}MuC74A;! zWck9y-0oG09B)#4RV>Ex{@>lac!W-}qTXQRA2wac!S6;nzNEEhl*;2@PMk(FkV1h; z8NQwN-#*c_-B7y=X;l=pQt{MZg@4I!2ZGL+`?-^$yGQ?4jd`2#*{*V-E=RGRG#^-f zD~ZJTd7UpR(7*m@kEB?vtRVe8UnP^DHn^TNjEL)+Th@gzb<<-$aHd_LFa>+pp;f=a zvgE;HKYW-XH(-4u;~X4b-cp3NPb2poDR)pRZM{S`rN01~ss&a%UxX_i3)UK-8Blxo zq@gW`Eovf9KYejFPfgZg7}w_^;IHloSP~%rNW)fw2Pc#4#6PIQKBLU0o7`~-DRj(c zhYWrJZfELI*4nVm+A{nYr{|>KCXD7C5(~YjZ3nLp>|ZjTp*rp8@?+AWRlwpEJI1o= zruu{ChXz$NyF2gnYVr1Ima@)iwfeE%{!{N(-W}L{#G<8RYA7RK^SxEP3Wj;tsEu># z0QU1Tw9zfkZVo*i_4IFr;pQegeU{u7Gx8KQ$tyrNdO3e`JMiM7Q8~7=^PqND#d4=f zvZ);DXL};z&p+3}{&HzEroiWrH%BUpC5HLXXQ|jbERde&h1Awm5>Fn(ufaK(ZwQ_h zWd(&hcgU?g`b&0;b0MeB0vTBBsH!W)8#e#ztu&>$`h;_iVET&&4At{nt$LUXB7+}V zD4ETpgwE-+cxOqz(V z$69ef(hMsG&YTSM3wut|K`sk~lcqwY4O1JJSa74Or3kI!L}q{g4+55r|72qX;>kRi zH66LHFVumblAs*E%fBJYvKr`8%=gBYf{K>W1-`TvptpA4!ftnM5^7BP*~E=P1(#-7 zEiCI1TR+IKc1-%;KTc9gUjc%$cxXS#)7TFZ=jlchW8SsB#qPq*x2{hdrbWpn&vsVw zOkTEEwFB%my#8M)`U!$h{OIYO;v8qKw5v0QMt4C|hLPf1p>PeH0+Fw2YjiFvRwi=fOvV(Pb2iC>CVvn0A{77akx2?T)d_B9KD-I-u~)l8gnK+YO1FV9VVXfWD}3P?iuur$=_{PA=H_;z0&j@K3Tgb%dioneW}xJ^-E6E6spbAYBI|>Rt+ekm3(0} zJ31q=Q9a4?TQI^ql7FbRSeJ28VB__YefekkzA-ou0J1AC`a=Cjd0V2zPm4;!(*mad zeZM3nu?S~kwIB-~BQ%o#o^8R-RFUoUH|n^pgO{plJjt4~~XEMTFBudE;#10I|Lg*>Valz0pRZ5v=Uj&&y-L z65YLHl6-|NMEQ&D{k4St72kw>_`0J*R&3%c)$sfS-v2?J6BP0Ch1Sa@<(xR6Kw15_ z1k;3jg(WZFMo*7Jsy9KAFI%Xdk<7TME&N2Lf83>KQLSES2D(Vxe`XNmI(m=j6S6^G z`x0Y~5Z~SwCRFbq3u?WvD?MdNgk{Q!W6X-$%-t)DXD)-Y5C1yIv^6=Fv32~6KgRm` zSGq}o=G24~vVfUkWbHNFi{-Rg@*LWe>U^@`6}WVLhAO1aDHj3y^ugvi%ScgzFTDi# zsR~5`Sy?tPEU{8iM(GADU?F6oIWLoXMT_qhhu1&nZkakP?|8ohbL!5i++fLd~}|j0V+0DfD7{P+ovo_EgM=vc9WPwuJ6uv(Ya zgvmV^_<|g+MLJDFAZ4<_ZGXsmNV*&}>lJhWGfscsO1u$DbGIuCHBC9Ft<$AvQjta* z%4a2^QVViBztB?}cET&zRqQdr99oSJ81&@b_yb{S)Hmo051!aovdfpTT`~ z@dz(TU5KK>q(EcV;neHlC}P&)qe{Y5%bkAnlT(5uyNuwy-zIUNnU<~KPp+WZ(EYMb z;wZRLRIc1EPzs zV1x&+J*Nu4mvVF&pv}#r0ZDikNp@VYR|_^)=8}DpIaf2IfbpD~f7$iwaEekop=4_-^WVMocam( zWiJ;7jYae%6!_-TQ zOgA)1(w14W368G=fj({^fez5w9KJerE##FJ{XEovBF;uuJJvP{v-LNpA3dc(Lf%q| z20Bf?`Ml-Xl>#>wl!A)542~>4HFJh2<9^=0OlzlS@5?;7=ae42yiJAitLEuWI+ZUv z1v%qKS;i$|hixxVN4He53DXg?dDiAw=%m2jhRZtVn?}!nu3dXT*{?seCU^v`l{$7M zB%P}XH|5^(d@c)$0oLjNfy|1SdS?3k+=O%Eh|T!CKuVyXGe%U*4JRj+^o53fkN&lF z0<^Njgghn@RJ1oTR*;_(PJtd(K>GG(&)S5QjL)oyv|3Dw;8IfrIlaN~CEu>7mm2ar^7)fvX=w2nE z3Wv&4DBA&YO^6K^SC>fCYcx#fr(#OCm7_;Epj|D|Ze!e!ap0k}mss5gJyc{ALC>!N zn0SbD$rEUG+u$e_B?&k;55`MN**7B=`Q#7kEBjh6b!?^u!RiuwkV-xX<89J(co86irw_1%u7@yeQ_nr}c^mq#a-OD76= zwvPEc`m+=>^&zCpTw621InDPyXLBUbDyq@!TC&SGto$5Vg3A0eswg^!sXFLEv=|qM!Pi&+ECOVT<%2zIpjh4 zM45^t-mVnzgR_6E4EHj00_b#6v$xewQlG$_tvXx>|Jv&=P{Z33@7md7l^QH5j{Nz4 zEZX{S4GGZd!ZiWB0WJE}PkdC}xja9=2eM(bwwmOh z+%FsLjoQd=|INfGtZacGJhDmTS-ti4vUpEEK=#zqwUD^nLOdVbC-*6mxq@I{6<%zNEA;@1UalC zIOPcMO<6SHBY)nj?e=O{APMdbcfe_!l7(CKz+gJ$IN z{8^{+@(JCS3Shj_0<1B&!ZHCl-=<-bE{=TQx*I}Gyp96$5RpNK4)iy_iGYd zV0}+&;g~NcK1I0sU}{5a92i;F)#y32Xf=LHRl7c}FO%!w#{%_P0d~oEf+2+!B0OWI z8xDT*XSj$yNTb#k-o(4**N^x)-e4@T8-06D{v=Wl6FGkz^u|YVqGRetPrNs74LGdY z`(57$@QB8K;ESm6_st~|LvBIF;@)@?*W%<%?@a=wV;OdlP{3yAly zK#tTeEckjbGJe!uwYXrvACCE zeAy!oQ~E;$QOHk&O{oDdy@l(&SH#(h6f`)|j0E2HKGPMYmavHqN zQ!I2S)|wo~0b5gw{!iarNo$|jWDcV(%hdUN+EhEnKZp6aSS`|Y8hcgt&5WBS-US@c zTH_5ox+B~Kh;TKNqQYYZx9C=E%v!#~D)A*|CN38ieQOHU7K`lX%n2{rdg6AuTfBbu ze>qP{o3*SD>f|cPVK%CyUQVJ^(2cA;`g})>x?psFD+O$qhf?@I=F7L&%`$Q5OKC(E z{LL0hBoBn(s&k7)?!f41HF%O-R4>n4YTr?3dHRvC9spp^ujr8R7r!#jDocxFv)J{T z!OwM-;LoSf#$artzk|s2Y>8R%mv(%As{;pnU!Wdf$e|z0BPUjyq`Wt4^^CIpyzar+ z8^Kegvo3z(Nr$L}3*M5rPw-Mq>s{;33khBcW$*}$zN0}XDUhof5*yHgdv4x=+Jx5e z3#6Zl3=HPdj%MS4aJaW{(~JNLDy$oQMecyz5?CZZ71g4TuyDa$3%UjwpUbenKVI== zFWl&{^^vpC&Vx;tTMhS?XfoP}vxIs8YN7L?k-vYaWw(;b$K1@E#@WdpajzTgjR!6y zlS*9Rp+oG*zouoULF0o6A`L`)+dL)t=U7WecVH)~+*>DQLuTlHGAXojCvO2j?y^wlBTTd29E6jwTlncy>-hOx2in@*bKaL!* z;~Jm9&e^lM7~TtNg2eNKwmAVSxc*BzM>Pqw&ZGvn{EfJC@A>BntJi|^nuFw3X5CJS zh5Vp2(+~J|^FYB(SVpR%vyETDG#6_h{pJGi)*uK~NUm|#lY^+MJ~X!Vgh@~n9NYaQ z;&~>G;@TxL&N!E$?XH(9;wZzdn`3NE*nl;2Fs_p=2oe<8rPbaFLLAC_nz#J7xKg|D z+Wnepj{wx1iBG^RhtF3;=3UKx@6&}#-ZJG(k_fh2h#on9ecuEk3WzNfKw27 z^;Us>wXLXm+Hqbqcy)NuxAx09VE2^e*Io5CI(7BGJvThIn;lJ4S{xtZ;V7LIgdHsmG{<{{O(yDnnn=mY9+ zsUk=;@m<1E5t3C=4sXNHUGxQ9hIzv-tseYv2-KJ-FH*Pjj5I&LVB<&f&-C{1HW8*^ zhg@w_QF`%%itjGLKn<%yP1BYk7tF6zBlFA+w{v zZcdb_xg{&`B=lXq&FPjF+-$SCn?Gwn?MXH^g%>gVDM;*@qtyr0j#a@&v$=NFy+n#{ z(o=0JUy6>fS|KRf+uC`CuHXi_CNj}a9|?-SbJXG3RLMgPG9X9RLPaN;?@w)@82azs3eSF^k_^7DvT}r4|KAEjNrQQJ(-Jsdvsm;L$M`x zVcE)>@|oQS)JdgRSV0opr*UB)kIY95K#7I&7C*^qq@44n=&h~3#26;)GEw6R_iEj*Y+Mxduo7rzpbDfW3ahxR{E zz}5Sg8N*{En}fCwRK;!Yh=3Gj$Da4DB01VMnR|)@f~+bz$m;g}i^@-IKv*bB6L;pe z_Rh7|?-CHKA%CZ(~%GD+FcuP|9-5V{syB@$C*Ys?zfujX{8~h-Vyvl(Sm-e@3$*a29 zK;VYB>fsn4Xz)nt^o6iek>#@`vLM2kMZRPUGZPM$M74tWn?w+W(sMyx%}s~UA!>2T z7&V;bnHbEzgGD)^3g72D^jqKe!?p;o5M3fyMLw)@c~4JV)RSh=+~@c++6G47d7hUx z_SwrngOpHAO14YB&&hg1xWeBC<_#JI^E{61Xyn#Pi$Wbn25Vqdzi*@rTW=)}PLp8o z9ou=mDT{#xjfem(G*veMd;U4~BrY6p4q(3w#9}frGAR%V*K|X#0i#mtSCMlu^ThWmUP<}6Rk-UP zeh%1ny3}VYE?<(apQFU>3*N(bRRudZKn7j zlY!#=;A0HzZ=XcmHI?{+L%(yTrunEo7)(`61Y;}YP#w8%XEfR}d|1J={>j5tZf? z%sZkDb(3)Oc*k7Emm)9h3CL9YBfex$FrV4LLVQOr5$tA7iMebtg_p(pQ97UH*bQ7k z08W|Dnqla!su0R1!4~j7n~Dz-TY%Le4=?1H?*t*8_DfnAbm>>cQloEJYz8@GJBSlu z%eH;2l>emPtg@`dj7w{ln|H^V2ed(~OnQROP*rcYLe^xn@g|x^DfL^#&_^zQ{bgrd z6cRAyiz<47303!W*epFrg0FP|fZ^p2*#S8MvW#g_Cvv3{s0H}o06-D-+KPpLy|LTA zwXU``FbLg>Gv(0SwBlC=`33{$OQQ8>|Hm?cqK96)%VupY?C{eV&0jgx8R+AVcBhE9 zRxf1>m>`z&({VFMtg(Yp;14RN3kPJzsK(N^J=~h~??>%vD*-~46Ne=xCyT`Gw_tY( zHV*E+s|Gx8{2L4X8h#&Xr*ge;B>N-g;JG??Z`;CgdQ=7iP+I=2$AY4KshikQ`bRP6 zPA@avM=I4uf$YHcb8^j%hK66QKO3=bj^g^%@_Tbps6o^_`mFt7J0}t21n%by)AJ8G0rv%HToh^XhoWGuh`iD z(CLa_?`QMRvn(P?nHpq`s>(S2r>MfDMWF{ddAYtzyOjCzeJ}^uZlVsve0#+f>I6hV zR&23lbBHxc=0?0L-5m0E6K?ZPR?E+bGwO=3UKue5dQ$27SDJ|> zf*C6wl;`R?w}$w0AwQgx((2Y1g9zYawW!atG~4FEd@}dQe?VF?KMQIGP4NGj0zRmW zJ8FOOoI>YAS}s_9nk}_w$Bor?3nBKxo&f*D&J%JI{AL2^#WGSre@~4R%;wzQLcjjW zUVL!g0VtwURF^sG=xp+KeWIyn09hXa8yKuh3YZ)62DX$(n-PYn8IEp0J47S2-CH2* zAM2z~zCF8><;^QU@4JAT4v{&nu~7L9O8Ml7V!$IQNOkMu{G76@M+`Kmag+7$aMf1h!Ffppmyr&h<3VhHTcZM3&OlArqXWi&fwoW_8tLnmNxNk{ifk;2r z+~A5EPwqS?6J?8u%j&&JEL!CCI7h&~`vRdsU76;_Xk+@|EsCQCd}^&Y!b1ZWp`{6q zap$L2Agi?FkQIs%{1;rIiv!}x#EAfBiLBVDi``w!ANs~gH=PS!Ma{0;EbZsy==#?pUz_RiNkr0OMot4g$W5@c>&EK%%AeQTGHoT zC@?a;cxR2{&|Y6jXh{bR$ZKan!g!XfOo$)KEFoTIoS6L5;MWYGbZ6by!JYKhUP?KF z5vmnj`Hvu7O@mxTcIEq?z}&XuA-|ky{^qB>6P%w7i%Wcndj_1a2plyY=qQA32a!3P z$IDw$CCZ};r1%UXX9(c+g7Pi|Db)?lG=2|%${#eK{z`I^>f|Zn$3^8l@NK`cxN}#s zW0$&L`%}NYE=K92H%{)!pHI+{^|>6qevR>Oc9}Yy7L=0q`~ck9`#zu=P9z<-YGTHw zFcm6To^)qBePBlS65=JulIJ_rd0g4QT)o#z^eE}q{1DGXb@jJwZuAAAxao7PK2khg zN?UvtBWFJRW?eRWhL^vn0H`Qq1FH7a@-iFx`0^haNJyd+w{h#EwROP4DQFD~qvLW3 zHL}_Ez^(rECD81#3$SQe0_d)P6ld1;i*SE(bA1uj;}XaaIpas93x4MmGBH1{L!574 zP@ub$$s~lIGRbH~k7DUu1j)h?&Qi1jN)TaWb~d{YCw^0f z3B56e^V%EpZE6ktGc!~6m_uMkzNVWCW^qoDTKBec57;UnIJ|ZjYvf=nV}; z4VY#@bwNN&)(J9HIG$LbJF3*5tq7V3)WY@!h@EDBdMw9>2J3UCKG!eG27 zv(HKd_?dq=BXrAM3Zfunv`uyS|A9!lJ$s2}`<7PLxcPm8BV$Y{a)Yd?4UfF%>&s9Z zs(_rSFzsedv8nNL@op!r_Y?Cht&G5Hcfk|?)4#|Qd(q5x=51BKj3>O3Oc)ReF5)jb zbZDa-9qz%r#dA}GUWsasBB&E5nu)$?zaTVNd^FC3gnZLP3H8`lZ=#38FTtju6%FQEGFo|w7A<* z52pZa(MX8iqhN~(;q!lTt^EQ!FcC?<$rFW$7tC>4FLPY9$^=g;>m%<*jdKY~ixS<4 zZ8gq`-L`a(X$^-pTatfqe}foV4*wb$uJQjxIK^PRUs0LqQ>R==HlP;iwO?Ai zlXE12?42Ww)<`L?G$Av=k&|g1wdi#@-~&(4BY~H9^l>~W%50bCj&8UnCF$_FOpi1! z*U1t^%y$HeTt>k-|Dw7dB}2n?#vkT7r}KM<{4tW3W2Jrg&>L1+F0L*f7k4!OnD?T-x$V)&6B^@zV_IY9e`z*2>H$6YFTQ28fL52HF0RE-OJeN5t~){Lw6F}c^p_{@{dO&B zhW(th5rG`e^~{4jnLA4Z?HzKRs8SJ;Ats!cabX7W+npj{RSW`;K3>W9l;9-T;mnLQk}Bb8*7Vno1jLa>8B%tG^ym#y=riJ3;5-c!FR;E+=_M$WY&g8SUZf_&xwN z%Hc~zdq+6NblmmP>Sz5m&|v0GtWx}@u$-1w<0UGn^c#%zO^Pd4QS}bsN5W67a?R~~ z)Ie$QgSxy+YZ$VP2=-n(&YgInYW9{BbDIg(}X)_C(+u-Ip@(9d?z! z^Uqz&bk%2+XMM2{E~t3x@kYqfFt>bvDC-!UJ_|l=ym_I;#fR4WD>#&BzNMAKNkGpk zEyedTEqA;SoC)!qxVW&hT6;zQhd0l>Yy7u&(d@$7O+P&&A0!Q_=oc^vXt}KMQ2gjK z=8g4n{>QF-lGv@8h6Vrv)HrtyoSO&Zc#gG#aOPKooW96r-t{WdIlu@-ZEt@5!h+kq zV(xTaj~WKf!~}*e9BuPRY8>h;$!cL3v7f-UbHGMEzF{lkLx7W!yZ5wFRCdt1DorhZ z26s;Oj<#E}pn#JDDdHmtN6n$$D2Fv4GAfzR-0u14$WA|spjRIClU#sHXZ1v2WxLju zRKkDar=T2m>PCtZ)8`9krt?!RX<^Y#|2j-H385Jr_5WNdOgz)mFFPuKkNm(hr18J& z&+fNhEG!mZWuD`>7tlCTwDOk8u!M?UOo*f?(Xd$;2&XX_yC1Y(W1g^CT#EOUY*=a? z!oV?qWWZcB!QG+*7Aw|mv1?m04F@m*5|?N;Y=@-BE7e|!i{g!>b$VFs*Tl7qnDsB zWh@;^0zuAMOyXkVn%iQnC0TuI2}1vBI=T!uGi!ciFw3A0*$)Oj0=0p3Mak{yQll{t zAs+nP&a|_84)Vt=vFYye+gArL^|50rg3Uv$L3Bh}Nc)9{&UHW1!FWn|+ze z_@QOIpj~L=!p`AK4QZ8m6 z=6vjX%7|K%6Sp4F6QcPLkXrh(xAk)22-f5~QFyZX0-SR4*weRD$s)R!@YZX0%UPE` z=`D_m&re`0x`-lT)shI!nsQ>q4p}YR$l}I$EmEsM{A!>saH5C0Tctlyr_Sw%h1H&X~T};(>**N%pS4WY>|eR2LA)K-&R}d;+P!HCv_?pc4HUKY1q~S+k zBi0k+w-BLi5WdpmQs6XHB*OH%A5?t3Y$7PTZN!fd9p<|crx^ozAK_K)=c5|Gx<`I% zcq<9rl;AsqcBe(IgHWITlss;XHg{NbdzvK@=2b&b+aSYe8M1qCJh^qb$6$Zq;-vjv z*TEI1MQMeo~#poG?OmF4g_0^5j}?n=%up3fwKoiI$Kvg)cTbBVy+)ZJ(j?Md3Hwq6D>lBWr%j!Y9#{Qr+0F+a$M3044Z#^st{ zvB`s(KTyi^EmP}NtR97tFAMBAl=!+);1XluFWSS?ZNzIDr*_6DFmoNLL~?>}tMQ}v z-K;g>7OfU7;gNhJkDtHp*wLC~wPLpeOGtltXEBm#Ev5HO9;MaUH=O0p?{ETmb6^Hi zv3b3TKKhaOS@Tz<6b+wvk?85EKkb)+z$3!yPEh`5g*mxJtdpzKitMhG8KGQu@Hd7C zBEyI7e4;jmMI7pcn!KG5=l?*)A~YwBfYZ-Sv~tmgiYa}H@>l-~74X0P1RKh#n@hF* zPOn;qER5{7cMdnk+SmT;SW5uvNm;X4{Q8|BegLryTUyc?=Q0e|6L6$A5i&XnT;)E#vTAjsAW_6D+FPKUAdDv<18|g9r_m8gYlfN9nRp*#P_t1?4=j1TZ8a&m2YG zJ0%eJFL110sN}K2?IHfmS^QW!L2`+vcqN*-VcQtfEJeQDnysj0Q4qenFN{-4uJi!` zXeiKf*--D`ef9TeWCls)SuRpxnu9Ctc)9mha4kdTJk=Zxi&C>SL)kfmGr5zFTP_)I zJBQsYh|HU6cy$)sxaH+A#gJt((SJ;l-u}OP(jtfPgC-?`KnvTgtcrsdwY5&L+$+_6 zoZD?~1t|m(*X#M#8u6f2Ajj)J%99f|W>n$DRCammE`IB(I9Ooe|MmmL*8myDnI+C0 z*n+@Y!Ib3n7JTatIf8zkVZ6QnNvl@fo%C6pe`}wDlJB<{>J5Xw@4%+qzL<_#TUz^z z)VJr3$uTt$BDx-Y*Z7Hywm4!xIwsfQuCFS|p$lN?evJL}LS*8$%ND(K4R?!y(8`m? z{&s$eBRrh$kc96;@w@Yko)(oSsyH#p;sG*Etr~~|dA?2rK%2ctIhjsE2$WIA1usz! zMA%;2f0Ye;5tF)DBI8zW2@^hQdWOeQ9$vigUr zl>p}*N>Ud!_<4KoInSJCz8!-H;Um=k%^)_U*Cj8+MwK3zOrTOg zAYh_jen!ZnmdG}~nr+JqM}3%CvZ^X2CHc5%8`{K6tFj#S6sZK#&YwXPJ7if8PUOp9 zJlhgtyp@10URk4u6P28zg@>7hE|I|wK8PW8@QpiLgk$yxb<*g7h$B(Md$+k5mJ@5K zM=VDyFqhBsPpZ)8yc@7`t?2h!fqZWf%xChQd#!|_j}=O!)3`jy0Yys`jQ^tZ;X^Hg zg!GJNi3p1yl>#Y9R1;@M;6gOaVLLoe`SL%|cgIeX@^7P+i2^2K-l5_s%;SxC(vwLV zQN5z#j)j%*-_I#y215ImKSSIcLnAq_f6ro@oJuyd_Msl%UjP-6^`U{2MkmLSt2{2}36gFD!ZMg#YcFakrf|}B_Gb0gSLqWdFAE7RX50l(TYn#@*BN%&$wDOX2@%>N4;o6<0L$}dDv=Bh z@&a9466c7WeX6Tu6sNmN4!sG=Bgv62ThPNAY>}qh+0kA}=#jxAg-`Jl|3l+^T24Sa zAfuK_tjuHU7;ILjZ&b4YX&@vHUJ(~8(oRE-xrE|Kp~As(PGc)273{k_f=FpQW{Zh@ z?uxbK4-YBN={YvL9b9U9Vol0!@~?v!d2No}1+FN+Xc9VQ+6i#iOVRmy3i|qk)@%fY z^|gHbC42%2Ebzu8y-E7?R}sIdWUzysWLHidmH8hR$ijnqfr;X$YDY#P8a-0DWbtRz z!(u^|?p-sx?}sIXz)^e>WRz;Lux@-Asc&QEdyEI93!~{-OZbZTVf5iFDcaxCt5!%D z+lm8G#+!VJ%nqJkrv!yQZ2z0DI%BxE;#<-=nLV#?vDglyWb5=NP(LJ%dL4xNo|g$3 zB#!>|NNP0TKhO{K;6MaD?F`FG98j*`jCHoYB4bZ{L<2i+*d0OSY#4-<40S zT&~T=$uJ}^y5GLi9;<%(m(>iC$>LMKd2^@=%s`BjKaVYNJC49*O5@|k?1W1TaG$~9 zY-th`bw~7wgQWb-dhA7b3OvY(tQ*T?@IklGuKhgWTg{lazk{O~%(~;7Vbm`l!!6s# zoPo$C_M-B%mnvy6GC5w>1ZT=W4e3D+(=o;4?Am!UOr_0R1tGVGI&ra&$;X0l@SM63 zvb{wy>?)>=NSRINiHy^6(WahA56W)4s&~)GT&&~!Pc2W;JK#?0c)!o9E;XU-qF&3S zq_;JIrW)T!4|z%p&J0P3xr`Jh4F!NiBgsFz8Pn3+J9u;N0WO~E)#Ip+(qrdPNwhh1 zjgx%j=*W$Bs{3D4+&w)f_5XM05G9W~vvLBQv^t}2+$(5d7nvVT)0lB(zT1r87sN_U zuK}E=g~>m26Kb9EXT4(p<&Z0?T3RoptEgHYL(?}GneNb;=0n1+T=C zW$)WaAgeCPFi{h=OPM!s{EQ@x#q<&Ab=c! zy1_Q)UphkvvWDt%9DfZ(50)%5arAgyiPd$H+e)5_OAa46FI9Jk(n7fqdY>d%BDzZR zK8o$ZHWJGdYp798(HKEo^qm^&M2~3xu~2h{9*NY{d}1uy#9cR;KQ9nj5WPTK(EGa| z|CtD~ix}E9Kf||JM<)}v5*5m;zG!CRU*j;P^WV;*Vj2Nw1ZzzFgPQqzdN{zMwU7+3 z?ko-JHt_O|2h0VFsW|EBL3TfZaenah=M;-V{Zx6PftZ@m^b9m3-15?Cx58N8|2TQ^ zKH<3gV9Rxz@!>J4)|FFk->{Ra9%=r_=u>k?bHSuXaS;da$gTrrs7q66xshbH>QrRu z(1JKd<-J})ZgaIxa_x`w{|Hz2Ni1dxu2Sxw36gmyp7C4&p)Mra7*blv9scUng)N3b z%aEXbi=rM@KFGF{0Kxs^PsPpgZQ^{BFyZlCJ&a{OtEski5%zOn=ly%2@AvlCXs()< z`|OMD*G9z;W%_^=t4__HFhXML1fN}DKWNQF?jI_j-(;K-FlOO8mStx)<&opj8pX#r z!B*IKDBNMk4NDi`a0x#_8FXS@7AS-aMf7-#T~r2@>EGlK>tdNIrI@DMIwn%xK6U_W zW(Z>=^N{drO`Oe#Jb(S_R!~fGi(ezNeB4owCIH0LdmqTC?d-QMBsyF_AhK>W(NJhD&EGdKZxeI#FGT*XZ zf>aj2w}mb_OlCyQJYcCY(won6%UkYpL+LA`Gdyd_eNyy4|FK4X)gvpVisR61JU5w2 znLhTZ9l@iDYXO?TiY$Un^%;l>qfQ*$%FDQh=T-NI50S!`(A;l zC?^Bm3Z5tK3x6^XeQ>rON;sX)An5mDS)t-Ig$SkJnB@#L?G_dXo&EBsE`FnNMb|LK z&p@4Jpp>-b+t!1pulw12#AW0#IGz}_!gry(Qz4gjw;gjsd2IkWh^h4BD7xRv?{O&3 z>P~<@-k615?bjIua@}ALi?jiDs*Y^E)ouF`5iQ`q*&J*NQk%^=PG6}1A7AhN&gTFA z{|6C!6MH6RgW9u*y{oEf)e5R5wxULf+Ix>yo1$oI*KBRELfce5%@ie6&C=SV-|KaJ ze|~@dfc%gnIj-yRIM4h2cIzYW`R4cZWk!u;&`J*V3*|c_?%X0%xz*NwRHk%$^NX5m z#s}FjRQR-&F}O)^zX|Ab%N)cs1Mqu86Ig%=*tD-v)94l9f&t8ueoFg%DAo-%V@1}) zvw-ZTOiGR`^e`#O<7Ns>m3g~aS2KUM(BMGh5C3YW9>830arwi~61!DB_!=B;?_hKN z;ah52>EP%-abRP0d$mN4RMuK3;-}Qa=+_&26~d+&lDSWssDKShKV=jiEf=r^z2RRvW}UlbvRFT6>28022xFB5Wm`)i@{i zs0K_{bJ)lUh!Xd!puG1DM-C;q=~KxBqg%u$af|VYsL^u&X- zUD(#<5tT(9#Qf%Z>;t%`$sydy3R(IHq~Arsm=B({bE@wD4$rYmcDG2x?9p zk}5C@Aizl0a|)DUsLLve8+^2SYP%? zVOeeR_QVzrzGaq4h0{K+LUkSFAx;8H7UA^LF$CMu zmsR+H+LxW&(cc?NL6SzoKEP8|2j*oUEU#;=emh>VbKj)T9k$Qno)^j@IBTR`T*fFu z=j>lL9N2dfRV&A7jabw%RIqQZc5%pRC@c#x02Qr#ub5=GVgpi{4Pj?n&X(Bred~`x zM-Q)V1tagL;S#}QT;~=afKc>FtX+ABU{$FR2GZR*&Qrq0R0YJunOp>L^FMgM@5651 zG^K~i2-nLvT?_RD6*l(Z(jKZ?nS=D0rE5q$xXT&!RC-Sv59Z>26Yi1VTRWcQ=YIhe z!sjPJim8a*rxa5_&p#USH0>ZZ5|VzeNBb{3x4PyWppTKvv)Jy|re#<(Cd;6AMaUVk zstKeo{=PXHH}&SM}^!Djj`#@gE&89eW#A8UG#L4e2LmyB6Sd zZ8dm~3|Wkjn(AbR>YwhZi!lJT@Vw275;5^Ad6)M9K;zyVCRrJCc{Wu(sOuB%p1xXE z;`Oge#56#}Ml)3jxwpQ+I)tik$Zj|Qhz>gNka4_1Zc}4p+tpAnZ^#tEEmc;_)GX30 z80RgsGLN2dw6Yu@*=v27?_^NAyjvrUj7z~;ne51Cgg|>aQPGfY3GpAj=&Fbc2E_i+ zila}p5~}KXk=tvkCL_O7dW{LXf$6#K(7%)M9;y=N6Nz8*Wzu}|CSvb8?u^DGWrt6; zF{zVD={E}U>f(epEx?FLszA9Uzw7Axgu-c(3%W)#|MzfmO8v?X+JuAyR9IL+Q~Ix! z`Fh_`L%!_4&}{@C;9ZIU&t+Tj+Tzm7z7Ry+Vua6{hE{Q>e&Pnl4MLI(Pg9k3dPqY zWQ2zjRh>;dZR}3Q>CKI$KmBJ+-pAIv>@D9f#{HupV^*P9kI|Ga(jR~l!H`pKEn0dU z?y0|TGO5uQ@|j9O(OH)_yrrTluPM$ku|6G5Ne|Xnzy6-=fUGBL;7!M#B<{Gm0zc`<`93nF zw%X6c`$nLTqN%SstZ->Tzut7t+(!OP#|@7RjK37I79g+V(|6+K<)HE*h6>^_6Rrl& zGZfJi_-zg4kF$=MSQg~{IMDE5ijKSyJobgUhLEOdC~$GjFP4rIE^hD&?^ON}7Z}<& z>uvbbl;(xcG1%EqDN!*zfRuHCeNyW{a=Eai8np_XW1`9ZTL1Jw%0x6j2uQKspn44% z66%u|FpQvl`X+iRcjWZ(Ar|G%*K%{hxWI3yp|LyRDvX_{kjqh0xS;!al3FO7F7CTd%v2{Z!bYNI<)_9>^Cjm@KYX^ z5h<=pkYbo{>D44dViM3akP_pTN+tiuct2+f@}6S9Q5n0iim^~4mAKw^O7{nAhGYf3?_!lDIL9eXQ^R^?l6t*N?PC*FT>|4enmSYh^iQV zWlLS5oT4tXGzZ-+as6_zEGb(Ki@BcbUS3grS-D`nZK7VN$Pqr4nFAHY#pYy|&yb|u zPWF)M_U;8DuH5bcyzTr?QF{30j2jXn;m0EweQS+m5{*qXk$NV;aKXx%baE_@$TWUg z!oa+g@b}wt1q#`Y4^Nr6rIER*nL7GP2bRZ(nc}$70{DGBWw`~jXBG;vb}l|V3=Cl3 ztur%|&uh$^)g8V%z4yGY^;*7AH*qU&9P=Wj`6Q?a$1~h`Y-KT&Ygiy3exS*{gZ^HR z-TU2L1Fv^hjFAtYR9Ld`DjSucP`!q3sDq?)49C4TkN3NHSU=iVS5nVDdw~QZ#qCjx zyNFvuC3{Fl? zDbwr9XE{iRv6A$>HH6a?)YgAPd2;jdQURsq^+Km6ImZ!hQfhQLi5YVB!OHPd@}EJ* zkXx7a+grh*8R4;1eGc*ZS1NMBZYrvo!mK@4;g*0qR=4*v zMwz{V(Fw>eJ%NkX8@}y(iL0YBIFIBJ?|&&`HF5CHfXfkzfDUHg0Jz{Cm)&Xbocrqd z%53sikaI@zqqfo=q@LOsPL+Tc0O#Bz=2Vam`J;O0EvUlIIlr8A084?B-f7m~6JrAA z!$;Xe<*bZ24#x`yO4*W6L&KK??k}{6;fuP4)Cg`AQ|sSfZhzSMA+q@;^HEOW`I&oQ zMr?tVoiKdQ)m!=0 zE^tF5W5)~u-WWnbR=z7cFkzk?tn#R7qps#YT{|U2Kw^8VA9Hg7dx%19TBcFO{|h$l zXhx6#x?{^L&GxNee#7Nm>ci<7Z0pcP!N>#y-W*^fnZH#OMp3)CSbIWGt?XPY8A$G# zk@RX@VSly$`#Jh+dU_2w2|xS{T*;m&ND1wr2PGxW9v3OMLe}{Np#MO8(SLq5Fe@Ey z`DgVJd@~JgQ}XYfFpo@sE??c8V!QR98lEyEf8^wVovo=vmwM`4sj+PuPKHFMz~@v? zI&xWN2MX3=Gw5jORG|Di5!^!`2*zV>tdC|l+q=)+{5>nB?pSk{QMWg__M{Bl718uk zOZLASb0ln0`CRvVD#di)J|vFyi{yBoP;7<*HS_Ge3{6eDWmFxql`T&{aXHP~KYFij zLk>@_<;v^4`vOb_C)tx*$CHAKGQu3#p_vz zxA1WdRAL!N-T8Db)kF!+NBN_73l^=^7;4*j(8&8q2&5P?a94-B6d zW(gW)qsCGp@Pp3QGnNxTu*tmis>FsxL9n-o<4#YzAP>D}y~KXFoR>RZAn0qt(^v;R zp_$*(NR>mmPt*i%oBeEo_SO=AV3zGLzV2Bx{3VVYjM4jSV&`l~gPqD4xp5O0ty{!# zn|*-II2+W*yUF;`;S4ZLrj7?UUQ^kxRPHyfmJ_qn-bmkj5rSS76!6+1alK zpAj#-H50i5-0aLC`FPJ`G*4%fUQDSKuo{yO1b@R8N&4?Va5d}H3nDU#|-mtX2W$V6R@2m$V>T%&@ylAhlt@5z zR04~-H>c8HIF&sg%i;QJ=lqjoIUFx5S$yiO#BsOTeWp#Rd#;l$xPjGxQdx}U`Dk*j z>AU8)P3;=QXBU8T<|fO~%GyshXe@4x@5YzTqDJp4L5%XdUt3II_=&VW?IK+qtixWmYRU($8sWwtKYY!}JsBhr?Af;tW3# z!L!#LA)Kv!;H&~b-7207lt8IdWAT17l*z;w8Vi${cv%riOIeL~xHvVC#ea8GxAuEl zcxLFi7`IkjKl}-PigTvL3HltZ+TRt=RFs z;!|OU==`9`cp}Xo3bT?dHYpUs??@cea?cVFoA%rp84X|0b(x4fW|!<}oL!s}z&HLb z!eovLyG33nA+3!$wf1hcLOv4%4Pc&tY;G*!iTVC!Wnl*bN!aqakdRtU=*Z!7ZTiq8 z#gNf@wuRg*3HlL!H_xz$B`r<5d#3lEEHW~UQH(u6?-`pW-VtW0wbQV>Oa`b z4890?{96a!92Nn>G^e#60;E1a1>KL(wB25%@!XXpu?yZ8G5na}dqYCBV9 zq7uk-$TFWU+%v(he%#k5Z>bXw3?W~}_FRV1d&2>&Esqhm<=2bWpisxS;8z0AN@*K} z!J>Di*u7pBRJmL9gSTpUW2v!u3t86~7K0kK)D>V&nk55^OCkWbE1Y^bEU83Z4qHgg z`%(3)hx^&)z=UCvDYaFV#?9hA8t;;nBq&4nh^wC+e<3i%-v6U$r*>UYMU91Jl*q<) zW4isTG%{23M@vUkmUy7vL6M*O&HIvmg2~4)~ocJLN02hx=cJ4GlkHiTR5!eV_#?OGD(2kS1 zI;x~0v$UW8K)Oc$!YR5xci?Jd$vq>$>oA<`300n!M!v7?LIx_zfFB>m z&z>^KXf)+|fQF8e7m3NFkeN7kftXE&b?x+n;xFHe*iHCy{5XKbF(`y`?=fvJ&*^m% zYMk%ssAK2wwA6$;@hp{YNmTVu4+@6&5(r+uW+4RS%#Lw`@`jMd*X*l}WoG_VPID+;l(mSqO|Br;Mx>4m+p z_5pjYo>m0L)@t!)J`MS<<-WPxic6lhJm;F#|JTb?@yM zWkGHk-4!bGO_+aJWO>ox*Pm`M!P@$(pIJU>Eope|Wf!Wm)WX z!U^Vswsd})0)5$`uv=RP*yq+tLr)|NP6I^yr06srjda#3eS6Fhteftn#vr0pcd~UM zaqXk!ZbW0Ik`P3o7uZ$BJS;2Gp|q?2KnDZ$JZmszDB%|K4VUY)5(bi49gpZM%XVeF zSymAvAFoj+x8ke14X$i>CcghU#Gn@zgFRT-LTZedu#OMAf3Fx75MrCSmqd6*9xWl-lCGQmy1cbx zS9yBGGM^hZ%-PJMbMKZO-QsfF;5}t*K9>b;g}xi`?HFITw#%+Prdet)XFb*ApeP-e z$jEOe>N$awI#Hq6ji_b2rk{l-RDs2r1B?i@?}S(LeRj-`3Ae&z>E&=gS^E245HdxP@bMP-%Jj(#+~X>7#A^uh_IK8KgzV z6eS!urk)WV17DPDbQ;bQ!nsz{F+K0{n1S$Sw76C$an(nq{Hj; zMzZoB*k}Dj<(r?ezq-qb^3#!P{Hx*Ul8mkM=hx!PvEY_u&xNGwwa)C$Jn@&V5kIBp z7}I~jI_z~nY=nGRnE@wI%D*8z5+|m^0`@yS4(6n#owbXfF=fJr`$jb|q|A=zxJQVX zxLf6K)U6ZVDK8B1E=Ch?f&@ZR-AiO{x{D zOwoGcAE-LOEoHc#3&K+dDdjirrmE=NE;t!3rC2y-a|?6}2L7wJRpkW)cE~_%q3td4 zt>D^lujdYOJC8IG(vu50fc?SVEJbSmepbqDzh!zqX1g4~bc|jx*Wmy`V>=f9AhqNie zDtSWY36xoE?_wux0O>CvSnIl*~m){YeM1EXwv{|Mnr2H0c1jMq{A+|{Ii$yope*G?9T z*t?QID^G*E6Gn&*m=bG0;i}tb0ezI+aXE>&XbB}5Mw>ip7S;UsV}$cQ5GYjJl*tk~ zT(a_9F|Y=rx-)8D>+4U5drYUPCzx%RDYnyjYlk0==88gpLrVyIcKw*Y7La4IGTuom z4QRzC^4No6!)jp!q%B^wh=&IwB4GC%3rzZ!epgeJ5fy$(Nke)V2e`G|?x&nN^ z<3!G=qIm)4q1)`{%z~dj01HwG~&52I}HyJg{FMI zxcmU=KAVXeb^S3O<36mlr-P1;o5ZLDLlKI&(X>R5Z%JxCuD;Jx%=oE&-ke#P4~={R zsL`*Mo6O%0Xe20uA3w|WucH`r_xkz6>j)+b71vBp(Sd`u(}L@tF~k7xjlhZ2y-(re z!=npNdwJVm?;-b6hKD8&VoX&_T!$|D`LG*l(W{kN^C z=eQC3u~c*n|LpUcoX{|ggfK3KP?Md+$|9?WS539iUhU!HH1oEp^R4|Iy;yP#)fRm8 zrL2@v7aPvV&DR#t4{K>n8i1EL@&?(I7}8HRd4vPsDbx)CGmJF6*TFcfCN0Ga0M%I@ zot711Y!N6nDLs_De)_9Ae>|kWpE%23Blgpy*8W!-BQlrfYkITPzQEcpn?IlxbU&4c zr`#Z}tnR^PvMHQDSeajr`$7~02 zM$Tb$ElO+e2eM6qS9W{_*${M>mb&#HNMT`S`Y*KP4d44NIaxltELKpHbYSm2X~5^f z$X@%6gm~JuInJ_ntX?g`mz5`^4Zxjms&Sy8q&_8JtcA!5>I@cH=LixjzoA47M5amukpY zFutq;_^z$siP;5bVbe6ieInZrCiaVTfuHub=XF1QU=3-y<{E|_j+w74X})r@J|E>N zV`y-T!7Q0lPh^k@=L-lGbddb!pL~wDd6>ICn2y&GYK}#I4E(SJ$RS&JnrV>*nMT6! z=Y{$kXB+ruaHL}*t~;quGh$SvY}lA^wJ+#!7w_g@;xAt$?kNAvlwiL zp;lRQdrTKcDl}Kb#m~y@*6P-#53yediVT5AOXz3|u&*u(pDwl0mi>N{H-(BMi$Vr< zccrjC@|)B(@mNaXd87VB+FNPenBvXwjZU58>jaFS#m@BlN_^m-hzKwJQQ(wN+Ao0&aAx z>9xM>b9G;AH^{&)F2k5d>~bT?@?>io7C1312ZakR2QVKzw`=_NXC$yvCB+|04}82W zpWD1|ocmVz{-~zxaUkdPV&!6dO}bmalWPbccBjZ(l%#v*$M5XH2xI8v&n=|EnnF|X z{;+*n;DQb ze8Eq{2N8+4e6o?Pmw@lfo$FS<=1YGfr$zroDE3(f!}r9uZ_JbOXj*D42#gpeuRw?}hTchz&B&@w!rTOB2Gf7a`?PVln_ z5ehjMF@xIuY(HN8VVy{HO7c!re<9B}Utetj9UdfkOLg63&pB^Seog5vmpz{-p7Vid zXBVT$7WG~>&@-J;J{P5_3&J{P>4b7(p9&R5X}RfSl+BJxr$mFe1HcqAEP! zxINMd1QMBFFq;*ugRBaFI@r)Hh^?!wD<9eKz5Qer**h^ls2(#dH{@NR(nL<=d+*}! z;w{Lqp+L^JwzDthVP==XQRm7PEBz!CND8JumngJ%{KLgHMRo~Y4N(5o4c2s#En8JH zto@o^bb%AW~vGsYiR`zJrhQ)a{4cZ&(3Zt&OBszL8r|N)%k|HZnB#>A&XZS zO#V{IB#aJc=|kMQiyop8)T)*F%Nj0xUR0 zO$kj00=~FdI2j)ktfd^e@}6<4FdOJyFvP0w1V=hxVr1@bdbHHqBEm}*8#`B`FDw@h z6xrl7nxRm-B1xOL5LgRK^nx!C`KP7Iiwh)WqgV+;>M-M~Ga84Z3;#px2tNBt8}gvG zxiS1pM|93xmVLloY$GluII;Y;a_PV1bwzABK%DLy{|EBXju;Vd64@_dtxFga=8ydc z+Nsfg`S<_YH&~%ZEQ6&Er{XqsI$YjN#@hkY=?c@GA)6PzAD<*ICHIb&(&$toO$Bt? z8VGMTBvf>#@iyx4$~lW|-Mm)deowG}*B-ee4T}r(IhZ_F|4Ss8;l@;ZOcV$QnH21A zf&1X%s&mmDZ9U|JwHNdNI2HSGb<{~Tv69G)P~XD-#U`wjFUtov8~iLu6Kd2htfi&f z_LGna)OZk<|I})HGz+~uj=qWQ1;{-)?77b%wqOZ(u1tc_G{#r82DTTESAJyI-}*fq zgUi{9*5)Cz*CT>#cWKF9 z4Bc$U<~FcAg71T46~UmkUx(NXI7`@n=Uw3s>lHma329a+8Hk~t=H`H*I~nR-AY^!n zK^n_Wy_LoN+tZYi{Lr_2{ca5DXe``%NY^XSNhNIV z%4ucaH!H!j@C)gaM>?Q4Awzw&M|MoEqCXI9C(8Qv4VVH^Wb=*-sfE-ur-c+-$U1CX zmq$==n>i!O_g2u5qt){KbWf54gWaMMwtrUQOx3#4JbeqXv0?@EHA5? zJ%ExnQ?;VKMQPkJC0XcV+<0;$Kx*Cw?ep=UWz!>nZNm}1nba%OJclQQNQD>2Dq7RJ zH$J4jy;8S|ILrJSh#~3NH1_HmeX;Nc5^X)ICwBkIeUEBW2+XzB&LzaT-mMYh_eb8z zV^`hcFSw(siuNOplC&1kJxjFIEVaSv6Wq26L+Hp&Mbw`ye+L>fdP0|fe*ulpb$G1d zvu7bhE8k2Lcg9+?G4T`Rd1f!p%JF0*W6;=smweQQA%eK+{|l|oL)SsdE|N39BYVX* zKCe1!_bfviNS)3HSW8BVLAo+f~;)9{{>CmF@*=Z=t6p zC_m<-zV2dj8kn`}<|9R32s|hE>zkdP%wE^q!8`CPMIPM$Tx*HjLpH)w%JX~s*zXkV zC{GEZ&I*;ZVf)Oox4Iw;tnFstt{W67U2Blp?TyfUMSe?JEi*iynf+yZun%3-|Ew@_ z_l*)9;gR?>iK&CzgSPO5YM%N zeqHx_a{glD+S=_!R^j#ddFt+3gXDHohCPv5T`%aJuPE4e{A#2l7W*lkvH0Y7JTcwA zk|LX08pp2%q>_g;AF;n6_niw8(3WO2_oBAd82;U1Ao+WL`;={ezAYGStHJLb)3(ONb1E2?HH}dm zej>Myg1Bh~+xta7$21zKpgh}RmwqDO$qVr}$ydmhuxk4W8Bxk%>{J{<-fAatq#6Eg z8-YnjD~q@$fJ&n-;T&~mU~GJ6EL}J(;j}VCa9v(SbS7iL8SZlSf%w!e(9;;drlwld zE4Ldk&(d=|jrkgc${LB_7T~H5<{3(zB-=S=8I?V0=RC0rGOlsolRzqTtRRJcMJ900 zR6EcQI*a4RdKXTO{)=sQxdr48Ki=pHwej-a=I#?%dOYhhx%Q+0GF@sHg)vAs4*wyw zE$iju6M%ko?k)R%S#F})!o$E58TejmE7FOy zrEB_mIep>FMGZ@H3O=ALvJTsvVvZ_|v6=mnP6tkZ2RBDlmKD3qn9?Rktm?Wab0{nk znQXtEI{)Q;J_c6pC?xydz56l@+QhHIiG7y-&9gDl=W~sY@hCjMlMhMEssq=o*fkf* z^}B`9z}inA>5aZLi;@tF*qAt|apaOqLd6Pk&>blaokH4LIMTDtWcl*Eb7W{#G0ox#NG{F!E*fPm_K1njmG9z1rLOnpc2qMrF>k9nO+>0f861+mHPHsuhr>&62Q2_e`# zg|VDstLB)O=|Rn}YbnGBt}4!*F?(!7$E*9D*I4MJ@Dwt&b(~E}Qxb}Nd)fARV;(~= zmWek-{*Oj(4!(xGWZf_EC^0zKX|5pmZ{U5xf)t|<-@h04J|*G56ezDs!{B3@81r>c zF-U;*J>hLN3cUw*SuT!Nk6dh)4pZY5FTqZg8eel`8DqITPqGVP=L&<{#E$Q!nxJ%zXW14=kRoBfn0&UITJ|h8 zYjZE(^KMWWvVj;skpOAgM zb5SGN#G92XRgS|=MEFJHYuipR?Ppdlzzkauoz~(T!M|O#HGN67kNqNWe_%kBYgtC< z=x8d^riNlZ3^Fi9U77YYpd4)A2cwTdTuUzLSQ(1}6wZNt4j*FK7!Sd(WMVH!W}+Wc zRV19a5M=>=kQR0?{|~Oi?@=oN%Is)7vod_dSUzLM4 zNhhOnacL1evob9yHxD1XF$UF;>CY#|b?^DF9bjuEayr&V-@6nEdrlG2)5|<`;6I4Q zbbT=SP@LFA|MawvH`>iVgR0R&&UP;z9u*z#*(YYdjJ%qWNri=?Z8XX-?SVLNXB11%?)J^tgvtNR0<|g+0F$bzOKINRpP6h+6Ur4um8OFa>tn6^AI*I zLyRDUtM{=h%`cp~J`=Mm`!XevD?jpCc2^7z1@f8Y6`BKbo&4sqa)QjrBLu({Pws`X z^T;W{%lfi^U1QFy?GycbOwpil1nz;+Q8O!R7lg9a%w zY8x`LXpo8`$GY8m>MeQ6F={cr-ovNIbarHc)zcW29Ng%@h_fsoX|DKSox@{FCP{Ax zXf(T1v7UCaB#nkL(EBRViH^b?FKVuxTF_U8+mhIL+i(@25qINuy^9U?J?bZlMsp>judSl zDe5Q@#iH!7_rz=;a4?;^QS)H@`~g&yqHUsLK8s4nz_<@_gG?Kb@y{$Y^#AsWi@%u{ zHCl1Kb%)^Xts%>C9!Bd+!hb6GffEV}P?KfW9w2j77ev<8C`K4u-YgjH%NZR^6HRxO z(0DMqxUj*nA%ZK(LJ-pS4J>6C5{P!Ok2e+nVmG>8Fj_J_9n$wyWBfiG=p(UACcgTZ z(QM3JOaO5^=&o0cGz+{aq=|0ig`rbrM`tK z)tv><5|RZN9IH)8oV3xkHt`VdLnZ z0j~KO?j@)C;gg^QUMZ=I=|$Twq{_gmyKK%#n$Qwie%LI_c#8V@&3nn%-4!5PgRB0f z_6XcCcc15#KE1S$e{{6Bn!ogF5llXckkq!Omm(t#v%B8dx%ijESphWk3=W|2M86K< zFMAdi=h4V}Vj6}y-3uwo@GVq8w6e$)=VZ&LA5CsQha#JEt5HICU>0@%!?Y$GH2hc+ zmlrTmHIbW(1wA6N9|ClsZR1Q!LoJ(Bu&J|$Et)T2hb{P3XZqnG_UX4OM=sXIKdc@1 z>O8G2XAr(7H@t--I_3U>EWZkWEU9E1eA|ApgZ$jrrT;pkq~JNlhqD;vRw|8iyk5>Z z#WBW@ZSZI34Qdvpx6efaMX*t#a?x{I~@Q%k1Q4f$EG@NyItN&aCzhI zt!&6$wiX=h<{C=%nCZT5$CZ)}dB9h$)5i`6WKWC-t?ZE$iWWICIm0v7Azr)Eqcd;+ zv`=CdMt%kj4upeTV5=|NU6njsCyE5m^hB?0SR$KN4d_{3sQxx=!d2M*;7OqPO^(q| zZX|JcfMcY{7mr1)5<550kwBMp+^7#X<_P|jsc z(5-Ipcyyj|TXGH&wEw~7UMnyea|S~U=v<*XvVNwNvvkjZD$Udj=13_fR-@29zJ^U@ z?Ba8j>8f-j0`PfdKM4Br%g=c z<%mwihw3bCJuOhmz{)$UlDqn9ny>0<8?E2rGM_4asotmWQr6VoY~)rP(R>;gY7=d& zd>qegqRgWNLBP0A;JR0|VicG{L-)OU<`J0jAGqq(_n|JMErD>ij|`YUd}h zkFldirBsJ^vK|B(br2r{vZX&1Vg?yIG3M1BYaw)RCPxAumr@6ek1L2!_osiN$;z5H z1MxZ@x=M&Hw?VWN#|u)oJ)EZyH#tZQV`4KK(q4l6io#AQ1)LI?0#;_Okkx>t!N=gq zqdj74$soh0&&RF66LIH`n%X<^XU0z{yKC7o5x}pdez870c6pmymvo#fU$wL*mhQjb zh+SXKqCBY1Qp_Jr(3uNA38GA7W`@$kI2 z4w~r?_6>%{EB?@g#u@)ExJmg|5DkcT$pVe6=j)pMJ^ar56@nq*P>8K(rtL3l)A}W{ zkT3ZQbsX4bQAP(=bGFFhSqWs4r2; z6~g0l?2#JJW6rhN^>0|C)tV$vP6nvq6x|Qm4*DfE|=getZ%5i?nr*k&mN{jI?->_^C{+t1(ep6kX*GL*-;xxEsfp5hP}xRVi-8h7-T zgEwxcQ&0}+lT|v|@A^(C$HsJ?oR2puOp#|`K+Qpi`nTz|(>}Q~AWA`gb*pIO@Z#X>*NdoYQktqq1H~$`?*u(M zW$;#A63L_Y?TQTW%qw~C9R`I1sb^U7^BkK(p(uuVO#AR?c0W`vtJyYVc&O8<<{#)6Hjad}F>kTH zD@+3Rppj%3dq_Qn*%Y#l>}-a;S3;ZWR<~k)=agS2oVT!C-B0>*`)~vmt(7mB=>316 z6)g83e$q@7`ytgYcRP|boEiOBk!2=1VR&!U;d~ZCbxN>1IWidZ@*pcTkh)~z&3lpz zR4e5QDs?;K2J0vO(B4VhBCYKV0!O`i(7qes{z(f;)@eAQ#~U?PTQ@& zJ|-W^sKK4!VovvBS%L_mBhs#sN~p!l z1Hb9sSN}knf1#|TFpY=jZ^5Df%-W-4>ag96fS$-Z6uFqN{!YP4A?XP#9H}86hz}Xi zjG|t_T&8>DXzjk^6Po{lc+&tOqGximXY=oAVb}(^uz%ngw;?46E zo=a7NgMJlEcwLue=w8ctOViA^hYb7Vp2COszTh%Oeq+DObs1MiQev)m^7}^u76Xr9 z(dQ-sKcdtAfx=t&svW3F!%mofuGy*!lW&h{r0DN8I+kdW+`f^#Rmx2_gdG1!5BJ6I zep~$pl$!E#Kyst>K^YvzQ*^V>Lb}0fqG^(;9!hvdU4xmW0N_EF!I#CWx-NZmKyeQp z`QUYp@*q#=iWr$)+KqVS^{6sb#9{37Pa0& zr+l^p`RP^8hKqejpi63H>t&IZS8VPpG~_b}Qg)P??*3BM!W>+k879jEwm|cgCH!q_ z`+mb)THEi`xXbU6R#a1EBGcn*n@=lb(jn)B2L~m$BKYRg67&>UdCnkc!>WPrz|x?d zf=dTaMmd}ID|!d8I=FMsDkvtKg#X;c&l6u%JF*~ym%Z-Xm-TWsS_tx^fzLXgT7|^u zO=$i`KA=w&UN8u-$o7dgnI)k2*EE>WVm<}EL{Q_^8C_S;5&fSLoGTiwCpxLHVr2=m5w zILdh3Pafa4Nupt%LMhueJ5$_>mWnVpewl;K5_96++q@fHZ*3ojpW{sJw z=#;}xi%*odxz~1wR4LN$r|ZPw4L}UXK*N=uT3$1D%*F+uoM@Slc^=A1g+z+WI9*6` zjeDg-bQ#BgZ^)2cDKf)z4e{nRTvu*X=m?hJ`jN*p)~A%EWC@xhPvKp1#AZk~T@HcO z@PEU@lk0tf<%~Z_(HxzQZ6*ks?vxI8u5^17m1B_I(_7`UE_(aF0Mya<{Zp4sni4L! z0>nePoddeUSO|WA%*r1{L4&T2`$y9Tjidg@b1t=wFrk zexcL+sxy|iGTSVV?RD+YF`+P1kPzenXie!ZFtCCM;zkQhMp?MK^4yMG)@LzZmZ(Oy zddbKeh>?-^G-l2riY-Hx)hXJhnC1TH3uuT*97LA=XAHk%eIrF=EJoiYbe5JjWo^s^ zZeMs%epF%+M`>_)l35;aGnZ>ZW`8;+J$KJTnf^J_!13?-hckzGKBr&%%cH9DTttbH z5tgn6?u+X_z@i=-Gn;z9#6gH3I!wV(CYUpo=7*5b zpl?{nzVD{l(O-I-*F)o4q+K&B`2lpP?hF{0;kASG`1roC5cNFoF~lwo-ZQy6W29dH z|M)t~za}5|?T;GWNcToam$bk@x`rT*jsb!&VuW;T(m6^H(V?gyAR#T?r6TYFq+B z9s~d>VpNm)KsH)kOInd&fSO8;l{{z%H*a92Yzl~z#;8S=6ao6XVh+6^^xj&Kq7sdc z-TOXx@QseZ&%^r~{Bq{=4+Lngd&^TnAItr}`+}%}0lN49^ zIp%U^+(UnnigAyTIdJh7KAT^6$2VNJKa=mpCGMNt*5+_EfBf=CN7H!DV``Jgm%MC4 zE=K`0N2O%e8~g9GG#Q8Bk6(t>il}IRsW||fnnr?% zcc+LeN>s2PS`{Z@Kq676XT^n(&(>m_ot?u}$n(-o3+l1A=*c&B2B29YEAiv-o5PfU zpqkFWGq(AgWWq65g1x@r=87))>i>Cg5LI#=s8c&~G^icwbDS2SXFm3ZyCvHWBef#MUMYU|F)EC1^xlIaxr^!I|Ss4O{Sy`Z!H0A-m zPX(7e2tgD~OehMcq8z5uuF-~GYa1ql4T>fE)Z?&vK4u?uJ05#dAdo*@hcB8ZTZdc} zrwtwy+_@15KEc-w-5o0!@{aBMgi#XfDh~I82^2qQmYx?lLr?ep^{W~zzZr;2hm3M( zr&d~gl86sp>)9esABH?zh20g_d>8wmbQhxmxnZeQvv&YAf~&F z^y*p?R>1{1NvhM|P0?EU^`W&r<(l??FF$)_>bg9fuU>0bcj&7XfJdw%B2;QodSBMv z*pESDT(4tAL6grc4n>-rzW(TTh53bEU)G0M1mCMxECq^NcFaE7nVy}zT1xTa1fP+u z&XLYRI;g6U&DzNj^&w~;8Iw`Z`5c^JW6it^1<~t70B%my8syq$FQBf3yYPv4e;nJd z3a3B#QQV_dsyzODx2BTGjVM6G&WlrE7PW2;ioRds60Atpcye+M_ZbOP_-ZBAL)OJ9 z`Fos-Mp$bhO^xyG-pD`D5k9SI@iaDy;vc9vW&(>Yjnn?b(0a@Ju|80QyldH}TgYD3 za98mks2Cgu@KtxeLtjN+j*a;Z&mxK?y>kM!+~QpsD?Rby!NQBW^E_UwRyn8Ty01fJB!pCFP?;Fdg<3M6uNfPff z`GY6zY_Xyno{y+(4<0-DJ)&=1rZwGCqq$P<)Jd{mFys?zNW9ptf|oOzw|EI^ypZ3P*mWNQZJa$haMVU269Kbp>>!B`n9DJ zCr)SK5k-VIhmP`0qG6*&?9oTHM1JFV5Z3|c!gH#ytEVv6-yl2dq*;5v@=KtE#umN# zBJWJj2{&UA%%-|aOXe)`hzv>i(EB{~G1$ca}$sru8}1DUOPfXU!oL+cHjqIs?9} zpQ~7@W$C<5P-11B{97in{)u%8doy?*J&DSM!JQIPR>>TIyRx~N|slt(DC{dI8MA9?&g&qp!tF5 z#YxX$F3Z&Q(qhVX4i#Ew1piId zMV+raAC4AsohF`Wt>h0>6RZ*@1Z_s-y@x>e9r-DYYqrUDXUDA;(MN?++P2%|@hC%61 zcyqb;9c6mb`3fJowaRu9lW;Ya%wedSwhPS0Pd7vo6`)Kr<3&DqZdjPF^tb&7^uqL* zMcsYScVD2Uwv^a_qFS=d4D0}5)s5g*sAqfnpP(`6+P1G@Qx$NeSJX@^{u$wuGPO$8x5|)rT%FjmOOS2uE@Ai)@9*ar67FbAx|a@&5s7 zX-ZoSlRNs}9Y@Hv@G?_z$*iQhQNY2pEOP^r;v}~R%SmR@V z;vE#n!}R#QBLEPV`gDDxBIm-lGFvdykIi9F`;KNjY1tbl$6Jm9b(V47PFgc9lXf^5 z@^2#e;er2<5aC;%K(K{7g$3dWY}clJ<#Q}Cp?W$O-YfJbKaMhoySQB z3z``z{KAV=k=ok`M2^MbhPslKH@8AxF8A)Q!|ZN0)<0_gb@_=N&-%g3JS=ZlwI+Mj zh=g7J1O1<VX$y9tqy{7+g37%44e6w_9>HlJaNY~^&Wka5qzRsDhVNYh_=G_| zT9)Vb_HcxRA1kYd75V3!ESm3cuG{OQ`DJ+w$!%#bs1FzrlR@BVGG=kHE0vrv;p)K_fp#!}1u&qd)e1|%vl#yl{qp@_*Bvq%^^YmtZdlwbNQu#gY*bEp_|ZGRNXzu$TNRrJTg{B+M0XW){_`y2?FH3iaJ zP=Ko_mO{h<{13F`DTfsZlzINZuAaP+@C!Y{d8)c43MqIgFb2@qxrwHBfTZe75}ten zTCQD-=Uj-fVY^77r1)wmH8Z_#oKpg{D2gd%u*$g&2-(S%FAy&psLdTSSje<|7#zy8 z7W(bF(4yc*tN0%x3Q(jzR`CoY1*oj29W^F2H(`%RjK5GBki<(fwlP^X4t{<$%=)qr(@3%6B1>c?@g8P`v zTCuPu5>D>j1M1oYif-JkmZ%TZjQ(^z$80aHkiGHAPqzh<1Wk5&bCzRgQ@yW&wawW+ zIK8g65@Pqd^4X^{6g^}oqPR?@^1SEgM-SCfVdsbx+Uq744!0THG!wt?p=Tj8rH3MoQQpAOtkGmMPVO95Lq4RM=I>nYR8MFzNHx{DgwG=IrhH z)*sUY=00tcnifi$_^<&9a2rhU@^;M<_Fbs(koEIh8;KPB!yE)^E^jm{!p?}w3e8?< z6ZSTbDyk1WzV!s3na8XTA-?KaOyb0i^g30MWhk1wAE=~v&%Tn~Ro+_qVtzvG=Zm$a zMI)My{yLJOwJQOSo&U>C@eXBUdA+R3XE=Q0~#Un6jMkQb0>d_mTS#mdT&3@lGsEnomV zSL7o!CEYzArZ0WPV7xs~NIO~Ejfc4~(05pJoYS=@C)ns>vy86A#I^G19HIxZSaZld+k!^p^E>&KdMbgg`^D%yBIaQ=3T#U}bb1n@AIs`wJb4J*mO1%*pNe=2if~ocuuC@SA=is< zKhDQD9wC*oUYdl~&M8O>t5EZaj;aw?51R{%*zN48l7D$SI52$p;|BwWvrjT%B+cQe z=tM06mqpeE{`(I!rvB~lzFVkOR~D~KhVJxoM1nv#Ny!p6cIZBJWm?HNP&}ztws(%;){(_83NHh;nV5qfI!eLAWI0q>$eIpKMscC`zbL5c8L%T!aL+i)_ z!C%sqh--FBI-HuGXI%h@1gbp4XsKw5Gq7Z+dYYDrU18eXk zrV{BZl9mVfGg<<}A(GB^({sKkz%qXOp|BFohk%(@j$px_b=a0JxCL=>yABO~b_Bh@ zPo(MZAMz^-2uZpzb5U4G_s^Da=O)&S2PrV2lCcH+eZyWj4CHe)L*>YeB>v)pnhWZa z1~Q*!J*8~H)kOs6GE1t@6E!h|$0hCI3TjQRK8FBOf9l-gT~X*K!9X{_6(PGJ;^=m# zd)~VY-*5m=8(X1t^lj^HarL$G)whIA>phTtHrRWcL7{7e#SUFMUu{HZQ7Vt&&XYCh z+j-mm-h4frI+OJK+E=Wi#&OIvIKHKP;^(FP4siH`U)PSdgl;^CgXs90$$7)`o6R~p zlO84FG;|b=^;|IQQ}OMC4a&8bj@a2p`5_n&f&4WO*C5FdR21bLX653(x}F}3Ckn@q z_L=&?or+Mt<@*j>ba4K=P`(={;$#pTLy_n z2c9XZC-BF;tAJVF>~8{lP5qKH=AK394`+*ipx*>8fZ@=C{S!qT_kW-wIK;EkdAFxE zAI#p6j#I3=_=hO*G0+3yOVGODJpArh7c+ip2@@Tsz5I-yvgz%Y%J5&V(Lr3Vxpij( zT6jVLF9~=yHRMo^oT+()BgZuisImfvLMqC`3`7eB4Akade78;a<2Hp7t9msI#j+<% zs=TG_h78Q0q;C#M>O#Zkda7^fY^H2+-c z{vYd|@EH)#6Hcd@RagpXknl9`(_h|RS6fi$6+?OEI-qraX=OGF1-ny{?K2*_FGwNr<{efC=2T(OUDe%^xKqNaIRrQF9*U%{_YIXN za}H0ih$<5bW9yeusBN)%B*vk*W-t?zjQ?+~X7g*`KajD&Y*XEgz4F%}fW< zrA_@ZZU}YE?d+9=7X1gLsf;MISh$(5R|bG@vdT~)yGSQ;Z-GmeO`2YgKgL8~tRS97 z)IOLhYu`h*mx;JSW!dOfDj=2jWq#y^iK4V>RsCQu22VVc`ZF|)`4lbN2hHCb2jS~^wJpizz&B-=mOp`?b@B}Y^ zb7sz7)+;YP;uQv~Uw{JLJUBd@*!Pa^&JrE07>+0d#W(eVU80}iN9hOL)J?wk;f5w8 zP!LvDy=J8aUwzYmpje$FW%YZw`0tD3|A??bX#_RYv})|o#m^__?U`az{^#$yv+x|+di$2 z-Sf)>?}{>*Qsf*7l9D6K)+jrBtN-9za)w8$3vp>tImA4uena8Yrs}hCm z>${b394w5ZD|4hXsv$tn^B(|l92t<59#@-r| ztshoLUbFb1YESB^gJDz2m8fhgueH!>TGEA$l$4}%lxckf*^P8ww#JgYrZ0QeAz*04 zQGe{!fi*^+jgG_xS;YzJgUOaI%vMsR34aY$)Gp1OTbG~KB${Bz*a-yNEVkv!c*-_?v#bCz}lkyeMk@v&7`eX#+ZQVxC$Dk!8_@sG@<*}pIiK$oqsYM*1-~L5Y>tOc z``HaEzUI1qHp|sr3ciUGW6`Ig7A0MtoU9^M@dssxK_X1Pc4x1|zL_&ns$Du}RQH)& zRroA7R?RG9mo5pU`JKGX47EnuW0(%h>kTd%IH zP6i03bf;xolZwv#`j@um z5A#J1p&#yPF8A2{yf=}Ooqypo_$!_NW6A*Z7wmWZWXwMP)%r`)%savph63x9N<@V` zJlX5sWty|&;U9YW*b3J=)&sW?MDO3_GC8~J!CKTA^SfegV2USfidUjaBiIHx@dzP3 z`2EXS4B21>Svy(2T|)eGwGS*mX+KJU=fY92N3pmMYDEhN6w}RQ3I9Maw5KfJ^&i)% zdn&~ACyXCEZRzbfQcbi-=jRkVF6r~Y!{0Wkm7_h=5U3BA*PcpQ{StJs-rGJB!A(6_ zQQaSfiM(P`%Uo2HLXHF0yc_pN=$;du(f44?B*dYUeVB=L9G7JJM+wtJI0>z&R9lGK z?3x+rYp)OouG9qDz!}p!_+`23%t4M8rM6ni2TWJ_YN?C|jjyq8BNaplEwWw?1pN~= z)Sq!IjL3omYP{$YK~rScGK5H_)ooH>XW=R9#J^h~f8`Y0PM$NWaClbbYeX?iy+zh^ zjBgtpM)-eKE!#KzEsgrpb;Gv|+tt$$nqNRwwQKUNYI&p$-I}Uddve2Ni*;)BU1z0u zU`Ra2qg!>bumk%%&?eYdFfhue_|=od>!_5NGM<92)*v!xSl;8o+?Np zN4HQC#uOf)L>kPyS*VKNIeCQfXS zk@k$%tfFf03ZuTHFR&(8acEPNqjgyqPhGY5{#^oA0%5B;R>-M>bQ359|+|sOb+0{5pVy2toN;TMxW0Ha9+`KQdjeETOvn( z0ChgR48)p@7cb1EAiv(0iK)M{D&F7c*3#3;Hu!F^CW$|(xe}G@jyxCE8gqHZ*Cg07 z`HZz$J!Iz9Dr`3Nn>4GQf-!`bhEzAdyKpM+^RmA*jBz!Ueq?=E@T0w`j?;agE^NQu zel04VR8ycxLj&1QoOHmC7NB+gidQ{|p!F>Uc-?+^M~7i)?!-)oPXxL1uWTUyA+m$o zzibI1*Fwiy+@DFoQ_^CM;FT_Da#?{jqFLTzPkvY9c+J$vnD5f;!r8(vn)m|odvm+0 ziK^rJp>Hy&)FVTfewvHW37Gyx1&o}Yw38jzte>apU@xM6WSs#J9V44c(=R8paP0#P z)zCv%Q5s7^*|mD*yP-5rg5zZt1#bez{MDhhl!hFwN4(XjLb$l<7VA=ei^8o7r*|gY zj$=;=26iV5FZ0((=wEhnjq8jJ3}-W|r_Re{rAg!2<}D+}y?Z?#Att8LDtG(Orq9L! zktq+Fed-X}r|6q->8mt>5r@VmtOt72XN?zY2x5Arlm!m{7;PSn9)wo;3eIs|E8@>M zxq}9o>ic;v7~VVpUxHw2z$U>wD6$iwd`L|vYR|)#f9f3N2WvDCP8{f02XAx4=}qN1 z2Ls~Cg1ybt+c;H)(ETRSFMW^iYCyC^Rq4rj*|NR-(GD&Kf=q>W=Ji+LRs`JW=p}P6 zGPFSbC9nU`p`}8~tSD8zXO;8Vve!nmEj*B3eQ~0E&zaF!_$fKxO~8#6YiJ7-M8c?4 z2ejr846PZ*?i}vGkSiPXi~0Uv@=I->xQ>wkr7C>VdEg(Pgyp^|#8SK#R3_JJZMvH= zur_szX;^Ha@&hE}6xTq!JUD$!ni2N;IRdMaBx{#_hfTuzlD6p_j#$(Bu17mGk_$qz z)pnd|N_wi&bH-R)F!p{)W?avxbg=OO0Dqs6uw06@ z!>gYt88HhW&)n)C@`cDI-P>XUz(6_28-(_cU_ zeJUSjQg{RaMFf7!Wm}Itb?l-Ip1=aW)7Ec^I8ATvh?&^d&j==iyFQZbVtr!MF-zsRfUU=z2@XG1uXhp0!9)qH086PPU+B zwP0zSUw%DTCJ z3S8}*K!lZDNsOZn6oqI0ws^y=to4!u=5!?>2Iu^2YlKwUZQq}mCPw$9F&8RG9;cit z#eDYcaut}@&TrGp$2^9(la{VVSmQ_Ue0BA+7rn;n8>Prg~L+OV&%SFW)6HG zk5>3U1(rD277G&u)ND-MkaCq!&o#4fH{$UFY5WFbE5DAw@R*jWt}W1?@u*iT*rpGT>ggF#s*RKTTqcF$6FF@47R^Cg%j9 zrZY5PTJz7)GRy9(YN%9VVPrr0Hg@~=?g%W7+a|Zf)$kXZbJ>X2Vm)3r*=lQlm*skH zImQm|ozF(i4;#LoVO3mFQr&AWqo`%NWiIqz|H*x>@^-N9+kC6w=JCgR`Oq?@^P*p{ zI}mrC?~mfr6PbvdKmVRMW_BJ_L43n;Dv=_&(`HVGq(Wb1Bwz$nWt*o`seebz{qH<+V~Ij6&oU(RqY$X^Hxc}M#8$Q=!S)j{g0xd>{_!U6|aq1 zK9p&WuLo+(v6PZ`BC5q{KXpZIj?e2m$H2B zJZU}h7mo+-sCh~Q9jqT6)asB2`4m0iK<6zk?_>9xn|V0uus~8=*is$?S(Ro)kpy!A z!=2LLs+pt8+WX2CfAyz=MWAB3;J%4X5g6ShNsjSX!Rcg) zIk=(>HEoAEGecJiZ8{;dVoBJ(hJnG@{Wr)GkP5$-cZGL#IiD>>^GiK*4w;v9>dp12 zA=FTS>Z>^X^Y5p!CBKSb5ii@~a!k*ZW6Sq` z;W?Z(QqKHI>?O&4!}fX-TRQCN#3SU!7hL*}d|hMAdNZV!j#ox+ef0>xBNyZQ$auXp zQ}8x2tLNx2TKhM@-o*0k5>`J$*2Nt9B9!Bv@}%mkZRRT_R{`x58sAom>@N@AfW6S|O=%u*2 z+pU4sNH2E1_u5@JSGs2%(`s2uaB^z_daJEb|!@A{ozdkT4+?~X}0O&DDN5HdKgs&ZwY zjS0p7z^(k%pwkqWC45ShjBv_-W4zN&t|Va$rE2S4S~XmZR^(Hq4$cvjP*+^Pb!CO( z7A-3&YTgqOaVD4J$ar^&K)of6tQNf}80PSJr1hnLx5WOH7b{>;80{MvRevO<=uU{G zZ^{Cnwl_{-L(C;2lOMVAWG$)LXTVzd;S3x})f;i@J@3NaY_!FmQ|2I7c zyizg$=_?e%{yX?DIiHbtHBk#za{;#;l&}~p_{7UB?kEgb&PNlGziq-75`JP?Is8|0 zQv3ZkBz&(LG$yCukNdpjm+pkn@v9qa!WS?JYq*plwJWd@TGWS&)?v!t8Zz08uw zl+lh4%sCp`ps;u%V}OKzOveB(F0!5KI(QYHbtnGZwzw|4+y?yp_SAdES;XAVF4N&fbuN zNbwWjC4f0g`u;Xc240SAeAYf?w=D@1cQd7%7b;Bdt{TLbqYo z7J#S6mB~JW23A<9ilKYO5G5+CZE=LBLt%0JgDV5w+mNLaMKZ0#j|XBDY2D)zy=g@5Pj^{U0@W_wI^PGA9|5X6q>S%~EHh0F|Q^+4Y_p z>}t$hhnWWL&A^WEHN8(OD$6UiMVOyKv|;Oh1^6GaL5{E2-3m9wfkh;RQyA z<3&W_$N7C)@=tQf43fY3NlXC_d*UigjTtQZIkJEZ)X6W621tL`Q|uQMdAaqZFKI{f z`>Xz(dq1WC)^oG6q`ixzul7VYQtE!~Not%Fapt#KH(+GxP2xjd4PaS!*`fyiCTDPF zCcJO{j{<9G{2aM=7PmvLr`f_oK;yWTW$;e7t#&B;Wq7$*Sn$b>lPb;3kQ*|Bzj%U) z@P`%+bKUUOYZS&#ea$yWE}#_3H~w5i%qr6bx_bu@{LR>s4+}WLQpJ#uT;{t*_aC1j{@1K_?r8Hf@@ZP7#&mi$y278GILaref$V+S0Y|i+fgpvW z98WHZzfW2yD4c1uFZ^mtBE}!NwsJwSnoJd)8y(pMvKJN7YOW=ny(}8n={NC{)bw~r zEzxbOqI=;GM^X;{0+7rZK1DhzB_>0&1Z+^OTFCwj>DGSOR!pK480x4bEczzF&^ar49xK_?kjdCSpLIsk5Kqd|cTlK;2-LZqp;A~- z$hN?F#$AO!W???O3fjxTsf`JZrs)0FqkU%O%6`zKHI2_(Q8%$!(qkc%a}69RV&|%> zd4k!R@vr_C4ZIon;NWs_qam>HBHcRxdqHg zC4<~)Qq&9QbI6k_bB6GGd&9yo|GXNlRXRd}vkBo^HqQgoCQ4a89W=B5?cOPF7xAh@ zfpaakSM+}IAWj=RmAb6QNsU5~cAhk9Hy z4o#%UqcDMq$?lTv&6qUy$YV9@o{9~o8C(x+Co_g@8acv-^*>*!mXUh@`2|A}edGT1?+yH=bb=^+Zi*Nca5X^zL-Q$euxkHB>RMO0g+{}9evjmqH!;0RHFaoWKH{N zi^dK;V5dc0L+{_b^L5cCWvsYAr?M4VVOY)F=>TMdXD5+; zi7fcAQ4kc$LPs{_oobJJOWyKG@D>7}`?ugQs#%otx3`lK%|j7MTejpRgG^=2Ul_8Z zUHUQg^q0XQ#)7+rflP+gFr`%pOn(<6&Vch(>_3#`hO37sARUYw$(q1IyRg!}_W5WUC z`N==fa?HL+`k|vB4UMQuYpmOYXp=JQE|Ln zA>*t?b$%1rnxQrfH}kkR=_ZH)4QB?*!cYuof)IGa!fn1+F8pPPfzUS~Q*~R72}C>i zQ+fv$Aw{yf@k#<3ls0f7OPGhR6qB1ObbiHdcIXd(*-+2z(2L-36KSP7U}6pcsPPMi zXK)00)`6$aK(aG|fv%!_dd?f>w{{p%f>C0ME97u}rpO-;WiaiY#=h@8Do|;*$qF+I z<1l%rY_G{elF`<5*N}xzWMn|>u++>chiR;7+^O2JXb(1b)06A`MZKIQFpjyLZh@Ti zOkTj-vDal9Gk69aEfl*jVArdy@d=9)D0IjK^{fqM5WHXy2v;9WlLDl>@%&ubzB6Yw z39lv^@g=XQJa7(1FCQvdMr@llEe&9XpVLpebU}g;<7aMn5m{gGY@A*P_|&Wf}#ovT}ChtBh58;Z+5sOgxe&)d={ zT=ggZ?1ufSF>X18rWie=mLaKjGNO{cy`IKI`7wgwPyFI=i|QvtuxhqO5cjk?3Kx?H}mdaA=K1HDF1;N9stXf9Xv2#lvleo?=u<08`SU3p;|sh zps4n4s`#L{=E-A9qK1>kDZZDQ7sk1jG2Si->XRoEBhMxmWb+L9{@P-X8vakG1{KYJ zQk9FWGkhfPj+q1AxNv@suret5uZil)KocI_h|l51v)*s2g(~Sp^HT@a0;m;tnpCF6 zi9_Z$OS?q0d$lL7?|=E$GyOLvKbS+mz&(8H6w2#F_jKG=b=}>qKbu{bR08clv4P~Q z)fD%GW#=foWp?zHEP>pAa^)$PuALX?-)%iQlht^Wk6(s_Y}BfIJla@fRT43Nb>Bw` zzw{Q$U(t@p5QwaHGFZ*toT@qTt;64l*8SdQxHY*op)z}nC9O9&=VYN)u;7|;a zm1FHFWp<9%2CUHFvi#6Mx#_`U-x>+$7|RTkz9_0p08~HV7RTKW+`m5Y+$@5Dc9KzX zBc2z$zAWhJQ#c;sqhQBZ1^TSF(6Qyl8n6{KX>LSWFrb&y*gIfD&2!xnPWZ){F;x=(8!|k`MSC+*3Iq&j=I)FQeU~FrM$+d71pO_bKlhObo97FQ1U% z6Smfy$&2_;sC5wffvm+-tG!;3@UlsP=gFR8B4fTyseR~JO5ALdk35g<*?I8A5+>)2 zbTlMKOo|4PXz@rQh&m>Y#Qb~-n>su!OQ;AvlT83bV*x`uo~}t-ir*5GeH$A;51XMf zEp1O&3Bj|eK+~(?8=3)E_B{1{{Et`0Ws}}aqN<&=q=zsCLZByQnDSp&s|D~<&o0ZA z0SnuC3q5IbSX`+NXUHaeUX(kOdf8Ep@HcLUQ_`CMH_>c4_)Rr7UrulX4_q?Py~gO# zF&VDE7LS>MzO_mvb3@K-$23kcAN)D0brPi96#}AV;J#`uUejyaV0`O!LqeAu!L*;B z0vD^WF?iXqbV;i^?(fuc^yrXR8zC6T@8LO8u5RL%N~~CSeBp>uG~=}vNPnp#vDk5c zIC^`)Y^L$qjTNWN_kg5tniq0q6T(nG-oy=Q8EFe=@>)R7rg%+nw9I90!iDUN8j@1kPL%ej%hwDH|`!J1y0Vw4(p zwT8%sf1@q?DM?Gft1(>g5Dgji(B3AYw+|2(etS;nS=$*ABZ@z6FbMhJRod|Ggt2$* zU~ID*P;6!;Ck1UjD&6C*ZF_+z`r)J<4UG+%h1!bLm1R^sh9};cz!DyPaKv8Q^-_+jo^H7;|8~JkRVK2o7Pi3a z2K;85X4Xsl*+*t`x?-n)XKJXu0nE4Kg5P7hwhL~rfLELbpJxNaBkqV9h-~SevEncG z?L}T#9%cY+;O~6f4mrODAJg~?J5ThAqD#Ru-aYG!L|vQ5H_ z+Uy?i|0N^X{IwDHtozTd2=|%`u<&z@TbsOR?9-dPB?l=}6dUrPtevkSw^_mHCv_W1 zR8TW^%@)jC-&l7J{-Nmb&^6(H_*_vp+Mt`ZH$bvKQOCRJs!VVV`3X5B@Rar1Aoz(I zaT9g5Sv{x4XSu?+(G=-J_}bcNJkOm5va+%GH;91OmeD4@ASEJSSbK*e{{5lJ;RX0x zhFn&*rlc8WdRvt%g|U@uk*{F%v9&bfJ_mBc;kS-b&hY{=A3Lz!e7 zAC6Z|Lt+du`8my23s`NmDVi+NDA>ci&Ahg-LQp3j(^-hA*e!Ct{Wfaf>ARoVT9u!S(03^c<*| z_WK}d_csm@#o8Uz8UAuP`MTmV(j^(%^My7UDhmQIVKud+DRi3GT?Q(K@svEX7N*@3 z+fNjyY^N2tGviXp)Su*h^RRxY7&BSH=z64L%-|E%MZf+FHWDV0qy7yl`xNmsR+s&+ z%|xG5RSVI<<#^zImtji#VAao0c#Rom(6s5NKuLVJE9BN>rm!!gn0LdzE%wj}V1m`< z$1E2FNVNB6u0sq#N>qEetoa}zqwz@J|H}wUMQ`O0+x`(1h@ZyF`%@8}`718l#eBs) zHu=Q~DQY$3YEf!pkE29CSx0Nw(v~UyIV+gBvd`0ac2C5-4<05UJ71w+p*)p)zm(*# z_F~+Y7pnTWc0op!3nUe-6VronVkGGwj!%qiov-FgHTfyjNfYnC6#!xt||HOhPW#YBm5JJ@ggsEAj<* zcEQ7QLVByMiBNx_-moBn^tNbaMT!7TSHr<#H#a>+r8b^arl} z1_)P)wp5c+Y>(tTo?Kf5Bed))%1)Ffojt{lpd1|ATNoMFl~vuW({Vbd%k+;?!T1a} zOK~^3?b6!$MPyBTnc{|Wj-;D$MD$OW_pIQRt1XB_rBu`#*wGSZxnH%PPl2fP;oZI{ zm?Z!on@~bb3xh@`#pM^O-iTd2plfR3T|qS+(3=lF|e zHAm->GHCp zmD$8!=U#ad4^H0XvMDRqhTVQeE1aQZMR?~x?#m*f`?ZJ!B`R7wq5Rw}xtz{!|09}lm4G$@M3kwwfg;CRciQ0q69Yj^WL2^H_ z->VLa@niJ!7X6;_YHm46?^`$f;jI+i+&40W=jHr!n+_SroG#!=wK6KWz360?QZtF4 zEp4-a8uo;-HV(n6s}@i08r)e$?m$klDtCUtm7&v`%x%L%PfX%n>k{}2_R_;cKXZuL zy?oE4tCQzKvVjEdYks=LGm|>R*9_ou&AzWY$Xy7Q4Z$GPdx<%T`GdH&;+?phvyPFZKh2pt%{zaq!G(Y?+^J7o7e z02T~PeIf(t%Q-Ij^qe`ngr*warwKEguqI(TBKg`x(X`@nh_i1c8;;YLg|Uj1(tpX? zLjr2qhc=EedmnfVj1mP4{PfJ4Dzt;FEvzW;|KsbtAF2HR|9|W~p33x`|b8& z#|Sf7FRr-UmN+j-TfiX(FBcz}eHZ}q%McG^lMpu8qMu1wunhJ464#-|*N&;!aIuMM z5Fg~N3tyfT@V0R3R61jcuAfBBxet$yXUe%r)>St(XJ1dw?4AK?xOGohYI;)>mveHC zt3Nr$38;myI<~TuOc;x?5{yK5e)?Dc>nxDI>Z7H0w9&sB$U84Wvlr>R!0U(CqX(9! z%oSN)ehFYjHU<@Y42#(oNzbv7)5(!%`~rd@z_p2pOc;F%^hriWRWz9hQ7pNAv!EUG zZsZWVX~*gEAlVI^qYbUh4{7T8vxnip6mE)Va=K=E^`~jdv&M8T+YS0lN9$2!dZIrM z7)3n|V#p;AaH@RKPv!&2Q7{c#sb}77K2hn3nVKiII?MUVq^I}{APFja;O)rv1;k$N z?OL32`W8aru&}-KVwyGZ1+PPs;<}D#bdr5u<|pa*W!ivY!sqz>Y;PmVGegL@O5@$@ z1<~fc*$cBiZu+KU;ZEY1*M_urga3oOQll3RaBbWmLR6@vYeA_%-hf{tqhE`T4)3aD zETPcWOkgQFqG`P4`@vciSqIyy zaV~z-aNXm}B(#*MHZ1Lw5*X{vOaW0aNrqlcO{Q!jkKuz-Iq9zofz;qx*GPQuwLW>& zc&OpOh!VpRXupjGFF^D-oRsBE&C|fuV*5b*RtbEq$fX}n zRLj=ueSHn&5|j0oJkVyd3rvFn!10zQ{P-&sy$#=xYp9i44oHwGfqW2AnLyOBZFr(g z-qO@0ngP}9hWi=`XMt_ui6cTWhV`d6sv-I-+@q1pfHJr64LiUCb~_ zh4VGdUoh2=_ZzDTl!w2qB!hT$-yo~}^spNc=toCg7mZ@XG0Bo7Nbu*&pKtY7zXw01 zOW(C|p!k~n%q#DC>S;O~Ns8w4T-f+np1e?!3uXDKo=Tb9@ltSRYpVZ~C(Eeo^Jr=ZavS#?d)_-Y{jbPw zmSgt_qhklQ-B3eSKGZvCkiwgx#3PES=#bJLbBrMHv_EBqBm)w4o`q~Ca~+Fh)&taJ zWD~5_lXfs1D|MHUVbApgOnFYJMqXJgS|mt&#L! zo}2@gt|A4E2RXwf+$!8qLTB6s$f(QjS0yH?c>QAmSnil27L{LG6-&tVq5JI&dzeu{s!ra@w83KPtuJ8h-(;dzG9M{SumnJUsENp2I z7#f{t(Uw_V#9%H;g;mn8xk zn>Lr&+&D9k*^a51AToa{xu}a~w?7fl4USymDX{|_i!^+-O~my1TS+-MQoC8niT=xT!%#L#e+=D1JT#m08(02+AUGXT3m?`7FivJu zI70uuTCP@>Fr(gKIP@Duz5P5&v~n`6TfJt^F>uTLp{JcrXSbBbs$T$53MEvf0c8s~ z@YKm4Yl3=JF&zKFd%-YA{jX@IzQ6lZ$8Ex|$Mo{|WCV{t->(v05^wLt*jMu4y*?Qp zdor8ucL*A}PltdnA!0-1om@KD((1-d*~a>-%K9MJXxJZ2@|Hwli^Tc!H1RcbO|9}* zx}vh%OkCXtuldvv=%>_>?TPVx*8^ITnSU{oj9ENmeY--5N|H^>-GcL+agj^*_6)VM zeGe%;GaL}#?upH{PR2P|*7=660*lR;c)>(#Vllb><@8pN%UipFjBC3W^yG*z^G$wa zhIJjB#EDvX_I!~5Q3h;tn8N(mqOBQ`%e9WLpD5Yh3CVwTt7J6ycU778R@A25<;y zeG9W>6>c6G@Sn>=$m8!+=}5P4{N~`y)g({h%8_S=a7aGr_8`Sty3j1X0lY!^8AEPk zM*W7X?XF$)dlF*OL5;gG0WRWq8{U+1!R!_tbmoKNLyDnRP+HDy%m9_Z=ZOn+>D0(p z{%2PMzUPvd+w;F%E9q+5F|F2_a+J5SHB>GmzYHumJAyqI{hf`D#As+ z?ynWnDNF4^j#jy{ZlH?&)ejrb!K13@ObO<@PEZSB3*ITI^Io6OBeW%qGxm+ zn}hR~Xx>vt;_mPo8W^-a*#3te>{Vdq5@Hg~8GVqR!)06%$zXU&N7hDRXR#QS@Jf7JcYz7J9;ml|O2`0o$7iESmcg@^OqKi-h7Jzqh666t;x z!D=Y;Fu6%mNpN2ih>#?iK4ReKx6<-%j*7^yp(mqxl+*VfBg@i8C9oc`6_H%-@rwjv zZnt``a@wzkDl~~+?i`HMb7l@WNzo{_Ga=Q(ksrXOCU|YhC@METZ9g+j>xUfjJbog6 z+Ghd}1ynp$#XN4ux!jZor(H*^#@CBWj-#*k{dNI9O7+P(*R^7uNH;Tt#9zw`4y=f+ zsf+6%$x--VsP zi*LAj>hg}e=bzyQmcv>oXU){$x})i?BpEE7nevDQLW`_OO#Y5kv)G+Crm;vQXNPw8 z?r|H{$=;W9**_J^gpXLp)r-XY=TVFwBaameE*#@~|IdvEeMtsxX67_HbOyyu7j?LB zp5EDXR%%P4vI+0Olx~RZfTy{GI)|`Ahu>l!SXcxKU{e&qTwwaTx5k1XN@ekW`)f9y zkKrzkgH+USjhd$SS65-~bc2_l?biJleD8@B)&F^xlv6`<=>rvtkZc4tkGEx4$8wgSQOPO8&C@pc=5J|MD3Tc#xkHmO&bfQuMb>q_w@L+QP{ey1u98aE&ABw z?NA|xU-?oUXSVts(4FUYtHY?N%`L?8zRoZe_`1Zw%S#R`e9J8#YVeznq*GadY$pDT zp^KMXeoqryr<5Opr=+5u!d~YAj@m__;2VF~v?JkNKyNEoUBzp!PUTM4(bqog(?I3y z5+NY0@AfE?*`0jXFCnYuOY8;SI72j^-B ziK9jgwoCCW=W7!TFd{!-%0q5grHCtScWaGL+>BCBoNF&33S-(ha1H17G-hMVFc7Peq5lFZR0dd;5)j;a`=ZbH8Hxct1t9Lx;?fz0~aF7Wzai4~Z1 z!|``CLJPNQ5S2=50-b;G_<(pO?&hLCOZj|IeI8S{qcT)e3y8Z$r5kA(2d{6XH~b29 z66^LE9rQ8;&%%1BEaC%2(~W3m-_m37MA`%m^7H6 zwJ`pRg@<5Pkh3A0)Fl%CJi+m9+Nwq2t7!qvW6O^0(Ob>=84h)I3~^JL6?8FvUXsDW zhUlu#lwiFrXoI^+bamRI$u2-MesS0wIGj<2;v__RQBUd4pklI0n7CCr#Q7tnoe;O& zK_z=m{?C*#)yIgartL3jIRoRvAO0+%reH8V#a#0>oT9%5iO+o41udP*Q4^_t^A{C0 z4!PG|=WO5nf@VJT@p*}CZ@E6J7sn>GaKB6me;7{$IXEmGw`1^LS>hV`x86ue9~%EF zOlUX~p5{>)iIqJ4L~oD4DT5~oPc!rQw+W@mcs7T3y!h*_Li=GUV_&l7NYX?qfPo0;n@#hyRLn9biAgB1%9jhOEmDle4^*jx?- zl|Xh_Gc~*GGKiulzyG6@7JZZ3b+;*$0N8D*tviDA4RaMm_M>FU*J!|3Z~=EK_JbyJ zWanj>#QA-xK6py^mDLHwK6?{v=qbLGLO`YPCic&N0PxiXT3NXYDr?kVOi%9W)VXXd zLlrqX_h40Dot|ZEr3#|QNGS5-?u|1KqK6mv??7%U04)ypCoFcVBAF`eht#2ZU}ryz z#U64~dUV!{Tz$Jcw1t}!_6tV$daLn9qXni#kr31e8mM7MS8NAyA>Q1>*d*)u+_&ck zf>r^@eYM5tp&gBo9Ip+lop-ldJss~}bbLPLf#1#I-54br#Y`Lea&JcCu7%?_2VHMw z>lRpdH|q|(--1ev6y`}z=~B2 zj$BUa%8zTu?76h^{wNam_&7W^JX=7ChXrO2 z*DqzG-*jzMIcc_Xdb$}N>n(W-t9&N*iA&)Tae(2Vb7jT4*;F4A@wecX{&SEnGe9Q} zb7ZtRMm|dwTXTnB5;UyuKbA4;8wes|4z(V`C|$qup6h5l5}@MDzaI04GJIG8lg%&4)Ldz0j;L(o4D~l=$qTwxU1Kt+z6KR2@DM~x#pNY& z+!y&hc^4&Vc(V!OPWB4N7SL0C!e#cpG@PlDLs0+%n9x4HJky$6?Npd?%{ zbygf(NY2uom_Z$t{eOZMaWhzLy$0aLC&<{!DwihbJUX5{Wb_}1nmnJsu!nqlZB8P# zE7CwdHYD0O=XM*=8>O@r%;mp6`wmv(LC^^tYGqI)k~T>~_4e7@nmE*+dOv2E6GBL> zjQ)CZR)+?YGh8WRN_dQ*8Q@u}IB?tSwIYw>>KlZuuWdXP_gq5fna>{Vm5O^|y2|cS zDON}=mh9)jk>=u#m$YjtjZnfy;PMKq{$8Y_1NF=WDtOwvo^ojjZB32uMx^;#vrucv zC-idgL6pLOK<7(iNviKB^M&7KFSg7WCIG*ZF^y!|;0s4FkHdt!t8;ANzQG%?efp-G zBL#nLNrx%+*-4-Sn_*L1usa1Bp&wW~)<@;<^v-w^q`!CB_UcUYuy2+#FSk(uO=-VK z0WXor3dcO2TUE)`z3a?6(qG?5ERb+?bk|Ti>O(L$FCy|2KG}jKJHiibun%dpU{7i0 zp6Q5wzNK~@uq>e4AV~F4zm>i27djUjIQ%*zA@&sQV!{N2$#^%pu;k?&a9{gBztvt9 zEe%A=rXnje~dUV-w1 z(v&w@!J9Yj(~yE8XLtl}l=U$4XQKjU0Ko9^MZe?$Mh)-9$tkTKEDOHL+cP6?tIJH? zVI_Tpna|A|Ntj@3bv#rCH9Cze`k4d7b_{k9mt!y}uJ=OO-GpTX*8cqIj=>c~NsrKy zsv)HSVuMcF1Eo_Z^S)t}Bj6?em+gkzR=Hl&cHxaD0cLLxH{7wP1q7PU1gQ#gII>6K zulylm+t(-&TBG#q9b9BFv?icd%GK$CF*Rb!{RyKbEzvC~JhIZHXkM2>e1_ZJj`4*X z(Q18-8dIRUA9Mep#gGn3tN%f~70jk)*&)zJ{~;hM$KG<=HXin+ zYP9X(5P5V^Ly@)PoB;Nc8xsxF_|s(B`@yG&($RAW+Q^nD18$;#OXJ8ey{Bzd5PT8Y zGh2D3^x4iP@Mg4hAe?Ojk{h1A!c{kiJ zK_pXtpU$vdj?{peMEx3I{1{BYK2_n8(ITvMnt!$`r(A$q(-_;&?2pbbZcC;h8=|#2 zBm!gdDT;{ua}~8I*3?CilxJ(wkw5ic07MQiA;YsDQn!&!$puc*Y)%p!I#54XpSj&< zeZ~y&9>W82?e*FBYw?k;qNLFPU}}}Os)NZjc_ib7fqiZmK?T*>$PIT0AE|o5b?Ku| zKdgQddE9)p?pO1b4n*l~!*0(Z`fSYv>>!;_;oTr?f*3wc_aew)a_TMcI`(sMen{0_Ev(ji=6r z?DRHw=1F82{yZ{QUwR6E_zZtMUlcK=ZaV1-efE#^ekC~~bkDh-TtFh9{Nt2BaXE5L zWX}mGUkt`VR7;a5MZ!~Ib5;(=ec}v&^7;Vg@O~Y|MedHP8oRJmu z=|*moTFEXFNMsWn84+x_Q@!L$e{BKZ*s|y_Ods)DWSDXKT;5T|dc~aqt6g1t&(F6X zEWp4(CH;e&Mq>1g@>hucbH-sFljMB9Kac^w)c@KG4z%C~L~-Xd7&8>y9A! zk{_}GL4^{$PSC9bL+8skCY)q^Mqq1UtPfr{jd2^ZataU+7k=}6 z%u?k7S-o8?T4VBVn#zd9lfde~$Y#5zNT(v+wkAa)TjXZ?Nh0wUI0wu4thAv`xT(Lz zO{&i;7)KPsU;bsJb$G45gw-J3(q4z`I_y_LfA+Ye?jVjJ_D3q_;4vNIme7?3l6qiN zB%CzuSh631YOf%JeGmV|A-VSK6-{cdQG%mFs8fo7h|u|sn0oSknim#hr+PF(6|tgC z_+QZmK#J?hX0>zbC}-Fh*)I|%o}S?z^Q1H2zVvK?J~{Q6m*6s(p-SQh1VcD57nI_` z1}q09>YJR&z2gf@@IWBO71RCNRE>^AKC@-=R4c#{eAO+X0JWc%P^H73f zedd3l8faMV3qK+?|1{5~Lw$Zm8niyDm`s11B5q^L|CthIq#|c@bpLJXqnw{J!PuNj zm@=l3*hm~Nlw%vNZ8qj<2%HE1LsiZIA<(Zv;PCrm*~8T4+|mGsCscF^?^ZmPn~|aT zK#Ebt^t1W9GS;_uQUG+z^R7FZi*UqHveUR%MCM?@6R6+NeWHiR^=i_i4Du={z4F0$ zT>z3c?n9Y$Em8@wVX>5(Eu_>_>p-!s`d*zB~^r z_g>&i$Lu<=Z7qIgg7fqwoI^LvpZWYfb{D)E<^(>4Q}+8p6h}=GLVNbB+i?Hd`|2rK z2u6W*2R|9wHhlF90qkj1ut_!-w})gi5;6A+M-=?iD2}?P_?!Yxmv-!PJQXRBPhQ)+ z`5Y_!#`{5vT;tZ{nhy{TmP0z2meTS33%_-mt-pH5OKwy@Rr~{)K=6xk@F-WD4VlH! z1>7#Yf=ko7I#nBi3ViJZ1nlhSoWb{>gjqtY?xw@0bTBIeTQKLiBzZz@Lb^lw&&v8k z>C;S1`@18czLecr#G*t?v}Tl-r!C;E>bw~g8RR1iz$P+|(UP*c73_Sk6GY`mLZqEQ z9lvuJGIj)?trh(ZA6CD)@67uYvH_LGmGJO|&f?)PV&|_yHSH5Nd2o;jzo;_lk_k^- z@TDKjxg?8h{VO;;R{-*|IsRQxj<&zF-_YVeKiK#u;6OAk6MOA)L@I>KrfBd;tZA^J+Busu|oJ4_XfzrrjzFvNU_pAs1y$Vx^I+nHtW*9Dm%b5wBm zrWX8T@=3m{=&>~`OC_35Os`yK6q-1|pM)DxQ8&FNcXFjFU=N6jN5&5og+M9Gq|XxC z=}e#yfA!jrY4!cwj1KzO@u=6htJ#0?rrug7{Em_$A2TD!duz;o1(KZO;Rd3`%{Vu$ zq7UO=WK77M7WhBFts*dT1d5XE7G(OqA?4>yc)%`ftX*6#eA6>W)nP@`{4R1ANAzKt zg~1*br`@2)^iDJE-Bv*S^w%bL2*uP^U^guUL?CHm4@=duIjljEg^p!__xoS4x(L@+ zTo*3q#)N}<^TLJQZ@xz0f_{v~6A(x-b zW$5=N@+mrUA--_jAlcP-gPWXSBN`mG{c04-Fr3HEvf1v6rIjPK0gZ0sFzwq5#92F< zUge=p!V~d8qhU+2_p~_Fg3cdqx;?=6qkv_La!c@2XVyWAz^3^NlrZl`$D)!7j7p1{ z%SC41yn&PSL$5unx{_$o97c!b7KbK7P!%INpyEw?je}WS|XC=KhP_b_E;)? z7xB1CSB+{@R;nwEbg*$XWe>JbJEfr?)@qrlO{XkX@{{rR4R^!?9y-yxZ&)d9&_;i= zjd+LKS3bvU3ZRRw146^&N$dk$jD$~@5ZsI%gXdqrk6`7<^)-dL*hw^IT|!RhfXMN# zJ=kDVCZJIg&<=cf!s<7+Ur+vpwV=BJCNH#+}e5p&d(loRSxWK5Z0?d zYNIGjBTnQ>$uo)yxrr=jZ`L0)@xVii{sX;gag+Ic z;Pc4ASOxXRRhS*Wj$zbXux_hi<$M$Rg)Kh;M5Bpk1P*osj7pM`<7-8pVF@O}o+0?%%llA}(dxtYf0g5*9QRVPBHJ zLjf>Hnp~o4t5PB305RKf%jS!=$L=W#8M6snjj-UMI`~L^8R!uqH*>4lEc5~6%LO9O zJDH?wHue<--s6R)X+Db-VsNjpDDLY@_DI9;=FXnpMATdCr%Vc? zvOFy9=!U#B64;>R!dSIrWvmE|Q*nsH+u(c8FaX9)RZA|n*T~X#o?n!<} z+iwBnFW8p|vdpuhpU1IjREqYt#l?APOFN|RE9@AbMYTqS>P@<+sxB;LwhKry;bJaJ zPXyjvO>AgzT6bg&Mil2Qos31Yi_|&Ych?Mb_mK0da&1B?(H3 zZ(4`{R%(DxWX9K89=I{9jN(k7v9c0aJu9R@69s$B;LX;M9+g}2Sv`?+Vjq_yocJi? z{MRnbJwc^}qdVEoag*6H#A%6o+Q-!oB9GsEwf z&)*`_H6k}Zu1;>lx#hJE)T21z#!&IHmWkOGGO5pD&5c$AgnM(+Gx2vPZu}K1_$8P# z+ey`No)FtRn4<;k2Q2e#vVKjq%L28_8)w{f8kbJR+i(^A`x;V#da3c!z>{kmoI!Zu zBug$%86pVQ=%V5-@ny!lkKV_Xjb%=;3@`#U( z*ku^zi>kie+on5bu^RUEJ$Gb*3GVGzgY+*)pTEt9V$B6vl{>hp+)$4WE6(#d^xkOtbIdbqW6P5}s`Bj&&Hp=RXj7j`Wft z4wQQ^y=b8eYlTkAK4$U4KPtvA8!X3IkziVgyAsYGIkG=#-&#odVHlzhV(KY=WHP&Q zUks!uIb7$DoMO8pqh4!pMfHfcHS{?*NS)z!!@GIP*+Ll=IajN`kDQLJ&DzK z|9PfqcI5!0juI~_E%PPzktM83D5xer98>gmL?STPrOsZ5v3>3rjEbY1&Af?yLqseu zXf_iIoRRS2XidBSFM=j^mBP6^yE&RuD6SY32=1$t$&+ONo^CB566OZ zC_nS^)eMS`%(7~|9CdvnC0|SBX)Lv7Zywm!wkm>s_V;Ei`O3a6Z1qPCxki+?%kwVH zk=_|)@;{xur~IwF|A8vX4QqbTLTf-@ z*&iZxa>66UC(ijwm`Y~06Cz?lSAw^3^&s@)DvMpvt?5y9hJ9b+7gUSxnl!oj)cJSw zhjo$>qP-+3b=z%OT4=1(#Qya0QO-6g^0<96oGJ-cn(gv?aSDm{JHpH**WR5oNPWvb z;vAV{cHm^#o=1bsM<@3QV;tfR`1F$MDWcAbS=~mm=^SrM-~L3t`sf#?)ieng&u=Ly zJ#zn{bdcZg-`v~`xhlV|UkSQr#8;tQ!?-K#ecH&wEp0qZm_6eSw0a<)VsUu$0bi3V>)-KaD(by`lBbSWCQ*01ZW$EZe3=7A z5O5iDZ_A~|tVMKd&e9y?ClusWwG{{w+|&z*yjwFmBpmJSqVRj}o?GocUwM;qtL~P6 z!#FWCIQu+0vwut-h&u-~vVT1u%xtfx$+=Fw`Hd;w3jQ%Rc9_4(>n50$;wUv3V|GwO z-oS(scQ_vJFaGt(W@G=$0!R}q{+l(3Xmw+M6mh}?`RBORxW?IXt8pU$#(_Pj!4o`i z{*_F(%;x7xAU_Qi*}vVb>B@H%A*ne80ZzIU;rK-XtOcWKwr6a!Ea#Ta@S4#yg0BHK zdzMZU6_f5zS0v5*%}9w`vviIAMyKXmy;ID)v9T*8vgpWD`1bv#O-$RL#pGRB(0Xv- zOWZK{usK18AmIGqFMC_!>mRV0XB)>wD+bczpQ>^qvXo@^X}ArBV%t8QekdEtps=Ao zXYp|3@Sw`UReS$^Xu#aDvy!P6ghvuQZ)HsjQ#y)$ ze`GB^dAdWQ$eZJSoyE>lQJSMTxf2m-n))ty@6FWuV@9pNOhpf_lqCG@95Q!XZo2X< zE;g+;e2GWPt@u9wA@NibW)%4oQ!YAp!B;D^rRZVk0m}3|p=jSQ>U%|iKLcvBAsUS* zF^5ct&_8sGSFW3P;m0;vtaCg4Kp(m(5lEgZ{@?O8HikAf)~ZC)ccPE0F6UKQsoEg} zZC|!W0R~7JWuX3QT`EbCsEomxS$>0myD|U`|8n=x({#)U(;{C6f-?LEqI5E&%2kMb z?%5;Dw)Xi{4aCW$?IrC@ryNK8#Y_n5ZZy~ah8P`xHQW9_76$!)pvRn5CtXFKv41!- z=F*qQv_vJJQO?ewD4t>SeK!mfbrZY<{9_ApB_Hr2_n5;OXl|; zb`iBBG4{p4TE{I>88Y(Bfdd_QZ@qzt`2_ZQ?O+3M(LWI0+uwNcduguX2TV0OPK9)- z&NNb)t;t3EH>je9lEODWocbB77R~)-K7UT&Z7;mK4D0UZ%`qV5XUG`~5ne|?;J!>I zd%G~_%^yZ$u?u*>;!}FcswaKc_#cQa(Msz#J^)?FGT+k-T5hw!$BnL)JrQXzrYAT~ ze+kbG#;CDsiU7|030wg*1RYVQIp};P<(D;zy7`S6YcHB4~v$^m|=|+0fDrz zLBr2_JF2AijvrQ5jcGH59g<^h{ua%5M z`_k*y^H#XQsuNOFJC~?DpSQS)goqhU5cA9ljZIkvy;H%jx*2v9B3-uYyr?*5QDj%J zR+9SnAHAd{j%gI%DJf}K()c@)cUgCC0^0KM;>JECw8hQJLXh_DpE+MI=@(v3shZPB z3)Op}BI&-;k#j4+#l@4fyph~2rrp7!1P6_!=&>Oh8OFiLP|R1Yo9;KcYm*hg2t2=3 zOyK7Gg*_OR)VP}x33fxK9@my6)T#Ch)@xuI#oVaavlOcyr`OYSe>GaK6_b(KSHWWz zuI(sC8rpV9N9IG9>*qy}-Y}$8W3G#EklPMvqRJ*aVgnzYf6nGLbiHNz_HGwR8V@rR z)VcbY;mwxZDof&nFy$1~+bZIN$a!5R`wJf!*&mhpVv9mToqswa`maC$zq&)Lek-%W zkCc1AvvESh1|r?G^;=E6<}b3)n8md1pvK1PPw_(HF`7CqWYPVkva{26(>%ng0?4H4 zvNjrc4(#%`>x=)6?U;e;SMJdO1}ACzrn z_IlY%6o*uh|DqfyF4-twKVLni&5(>2$g0G&eDRI)@Ve!3C`dOPLHTnSTeuwX4kVPQwlcDoi+V4(?>7PDh#<~w@`yv~g;V0JfF&YmeU1o#_ z$-Z~2#P^8|8UpQ}+LD!XdOHbMH)0iye6=n4s$*+`BWBZ z{{oaH_%5GYp;EY{KD9nGCUFJm0zn|W)t1YKx}msDmR4?%J1uklC$Q)hL`pbOr?1BO zb#R{7a>ShXW4bJc4Xx=KTwX5kJBBrFI%GFR2cDZ|H)YdY!~`8K22XYFXlxSXJ2a@L zQX@_<-ao=Y?Q_|b=;~AD%YbXSA7S6sgIE#s#r1vwJo#7pNihOBrp$cYhR!A#Oaad- zT?^RJu)2NR;mFS)<3U|ZdA}Y-t%wHc9)Lw64_O@6FuYo%ePOs|9{M@w%ydSS?%qkVyX8R9E_ zgc44#oa?ta2VGdx>19k`4Mms5@6y^=Wq4`)*JKNEtGyAu_jjthg_E*&U zjPgu6VI_Q0P7*0aHs*|CaO2b;-tjf~W#+NX-!q<%xSnUdj1QHI;sA>dw( zWUxnp`=K0SEbE$3NVeS81)`wLlFn7$#fr;{B!+2pQ8X_3%*0dbruVV%HWx;?NUxH6 zee9ihx&rV!6oxk&2Mau7#`%|=fSg1ZpPJp~W4eYLY0EfABFjxM-QY3lOc#$I%zCS7 z4a+1OT%l^8b+u&3r?e2ywC6IY@-?x>7XO6(`g`QcX8sqf$sf##D#2k&N!5RF=&P#U z3N{}lU_}WqAn)S(wxDax{ycc2|`}{J11$UJ9>Y58er0m z989#Pz|1x~^8Mi6x#jUDvE_EHqU+hb`j`eGkUR)P+_=+wP=BRsOeb1?6DcgW5|Kt4 zLHBT^kwg571jxR2b+L}uXDJlMtE`(^%?gSzK5X&pSy+g#5<41akc8Y2+!O|H4mN7E z?sWok>i<9;8X?2L@@^VbqiO zPz4jTis}uc&njoP2c2#NQhe}(Or9juM9IF!GEIzlqb3Q< z+JeVZz=VV%QA)p)%P5oOSf1@~=^W8~>+p_}CG4bOwW8}k(52&5{Z`cIXxvACwnQ?C zInRLOyuB-=%EKKkGWh>J$^ky&sS3Mm%SJc2j$&q*n~R0*9w>qlQ?6q_V(dAkQV%EZ z^q)Rq%jpLB8ePCW<88+?Erc(aL;vz5F75(S(6_APbL%BK1t|~A3a!FsrolxD6O>AK zk1(9`EJw8F&Bo8?7EO2_-qGS_DC!*G{P@;*%aGl)LnAkd?|w!GPV2_8B2V`lbl!O| zVuXvVr*G9ml&{XfjsgGW(w+m2&l!oPk6-e8^@8Lnoh-M_62(8-5e{+DMkrLNOPL(+ zz#B69^`2C7!Gjlak^ElI*$GNeup^L7xB%%H{)zu|7fJPQ7$1i zS)k5_air}Ucjpo;-2eO}J(x9S&~3Z;=sQx^^V(kw%K0u|ELzr`R&f{BE@%=s5*SzI zGWkB0`_rdc%eVE{RCaWC-OGpy5+Flc@qDf7yvUHg<=xI6s$Q>=+%iUUIo5_SRrTtB z`Jlh=LVMDf$|&L3BtaaP6+5Zc7`5!^56j3j?`gP?0!^~Zk~Y|8+LmqJ&-s{*hlo-V zwMlLDwhIeLWsYRze zP?qbcWOzLV>}HL}g!HgY4>~FGe(E|bEP5GXzGr4DA%sTUt(qyh|LyDjU3v&C(`^+v zBLZtK#Vj-0>f$~Sq#V*VtaO;=ox}kLoFm0i-Fn?`F-_6D(>V&@ocu)Nmp;+Z0t6Jf#g|1B@+cC%Cm^_9 z$!)@zymM@mkR)$hm`HG2!URQO=20*}gEwD0(@&AjDsZz#HQX)1N!ubW`%1{rKF$ zWrEFY9P2O0(j~q|_Z07QC3BZSeZ*buB)vmk_HgdN8CaUBiql*Vy?H!e(bh%(?3G7?8q0nS-}1dv_5R9BM#JIAb+l{V zS3FO-rL354;Z*QY5z|p2q0G-~dwI9wO@3Ce^x}oKSZ8|&=#L_}TwO$fiQyGGe~VV< zR5T&!?yzommG{`1Bsqa5f6S7cwb`xf>wGJpRMJpz4Ni6^BV2h~&!vW$ub7@q> z_Ca|#|arz;Mv(Nn3RH~DZ#sOYL*- zGkC;JC##(s&kTDPOTg3Fcl5}Y0&bS2-XfN8A?1P`@)MGl1Oms~l?Ca1V5lFwSt8I$ z2@fv1ur;w#3gr!%#S3_d0gf}sC8SZGDmRXdLWVDLH{f^4jw3C#?U05QT8K`}BUH=1xcChhCFbS!C z>;II$iTF3jZuOyU8Wq}eajnQg)VGIXnnfKDa$AG9l!Zc@t6e4KbWULib6rPL#={wMt|d zfdq=wI>ebR6+3-`b-qK!9c-3R6jWS?>NzWn}qN#CNJZUTVA;z_P^cT zzV$H!D?$5uxoHnJ`bBPmk@+~38;4k!4DKW^W2&d}`S;XF@T!Lp{L+6qfmKv(IlUP| z?%=CDiK74Lk<^kR(p1_~Y!XTFTWKzh?Dr(_l4!+gP%o9e^f(v!X!3a{zmI^87ga<$UTpq(lQ;5mT+716^93ibres z#*Nu$v5S^e*u#U`aM-QL7u3Iy zZ2J6yt1E=7p@`+T9&CfR3ka;vwx<@{X!{MuCNGUDlS^I zT)5EPxH4n;hYf6|60e~|;;726pEEp59!9V^1M+(6Nbhb_Kh~QapECc&{ZG4`wiKkV zM6XS+<~Tfjx`5Jfh;Y&K_7y{N>Azkm@oC%lk{A+}?K123IAly5SVn3Ueu-0MWwU^J z(7m6*zo3`v4^5?cbX;{xR;$MI$S;)bhG2p)rP7A2(Rz>*j042?)Dh+DsAQc{^^|*l+Ku><-;s6+C_|1qy?u@COr92{r(YIoEpP!y2qsY+I%1Y1so*V}e|c47FcaQCAe1A5km zL(#mVX^LqD|=xZ&`ikvy=1xw*s&k*@b> z0%%H&`AtZ~+zmm&_px@1S^E%aIcFxaqRzLC8=pUcV1D3LmKut3`W4kE=(i=kGCHjw zxTC%m6;oI{++Xp3MEI3!u7Uh!Q90aFjIc0mMnmKwi7@Ix+Lr+%`YtaXKG@-4Qd%3f zm6W8t$4l6Z&@69$H(Tln)eZWnEavh9&{TjQ)kA^8W6c}f^wi56SxP+SAAhaLz=W@3 z=YTg4wZeG;G1Hl8De9fxoza#|yG)5k|I1VBvYio~x2WA*3nZ+$2FyZtVYUh2 zsCv;`i9t9>&Wy*y_lCQ$VDzSd0DZTHx0Y~OOYoB(99(JE9`8?_*R)e{PvQ|-8J*>5 z+^=uI<$&%HG4shuJlN_fLEUWQ76{+xVFF2X-hUwLTBu zD`J{I4;(k@enH9-x{gfJu)JYDyKTQW_k7^KU&`rU4JA>qH;Dwsi&3E|`&pdpN4k0_ zTHHnX?I5nvuAOk2MtA=9*(|B3om<3~G5U_OxGQZJW;%ZF*)uzomRKRbN}PyJ_J@yd zTEBy*v(^3|VQ&@H=Js~+1_>72C0Ga^oZ=Khaf-JTD^3f=9f}j&-Jxj#J!?L5{w5uOS!ZCG!aJ9{mXjvhj4H`>Xk$o$ z+U|yPJNf$$lM)pEbn(x&VcHUV4w0p<`?$OuCBz)&gg4utsI+W_uI9EspV3gtYD=40 zu!&bC&h|Jws0;lEy8d387~Iy@B~V`MsdZHfIs6KkC+g|OW|M%4>wHx_k^Y0nA5X^L+ILY_@eBPE7BXQcT}xMAMM<{!0wicn89>}T z!&ENcqz+p5Yk#$3;x$^<0e8S8S zmnRv+4clmlPd#yj3+rdab6TnHa~lH30DnD3`T-x~ybOh@N4Gl6PssE{9_y*-a%`@d z82pTi78M8!;LiY{0grMc+!o>zIE34hNo~NexD;0z#ETE1GJek>HLbaY%aN8I$k_Cd zF%c#jA&Q$z2&a5k`;|$gQUo*_a?QtdO)i*I5uO>w+^m~Ua9E2&j$i6z6le@i^QH=n zhq2>h2%LZKE}??Z3gv>2b~y3^g&oAT?vB^LBh{wEgvXqw6m@vhc`^nCro72H?_<4=k@oa#n}(o$ zNF!YnAwHS{l5V%JEz3I9|1AN({_@P9acy6$p1Ad6ia+o8gfGm<7?zPgm}J3yl|hmv zAppl+V@h4V_Qr#T0a{uq6%B;TRONa1p4B5N{WviP+4~z&t=uMqAI}(eLVcL< zuAXjEP7@OqgNsuWGpXu=Mg~6hq^jaCUBaL!?)}dY#jG-BYMSM4*d&<$`O3kB}YhJbD=QpiCXK8avI^!X{P((VpmzbB&3yPW0uW@dRne=)ei}bzaqTE?rIx9uaBUp!Rsx{(NYm&f)o6J(sKwC~?xjud#dm zYk9|Qq%!+58+b>5UY5s1PpRs|BaB+Pv!b`YE8W@rJ>DkWqe&b~qtQkrKJPtm>y{T* zkiRRXDf~aYtbhQ*ChGUZOkxIfpP1I?cFUSTr4iHB`HKa;&M%U1Z+p;Zr9V@U zljHUsxcz7th(3t+H6(p?_C>MtaI4a?RF6kJ3~@Ml+iUon58yaE3i48hw#ci*a{JDD z5Z+6PIB*w`NT^uhgTz;w zk!u+e{}_Lg1dMMcHbuxNyF#)I$p7XxKE-i(#1l&7pS zcas6bm8!QGFqKGtgsU?X`}c^iCvo`ss*3$sLOoM1Y5Jr<@THFS-I3m|`jJE%A+sj` za~}O#O8<%to5ce_>T{hfWD4r;fEmSeQpExl5{Wroj3&V<6KnRtrCvx0`X}R4qqz>C0pvNuDE`I2o=`u6D0RzQA^3>H;Dl)b%}d_FBV9SL@fo{`ei}34 zi_64_?oO(r!5BKbJz8TJZ@0uf{emh=huMeSsbI!uz2&_H{zG>|x6Mm(>L$(X_yRlk zN6aef+m`1bn+G17f6#OH#U{*xd2;U^H@w}I=p$kM>9VVN@m-Kkk{?i=$ay@X0n~d6 zuYfcofh*jX)J^~oJc?JGFCsj9wGq2qt3{6yLO$uBCeUP=EZHpe13Gc0dYDo=^{)w(9?N?U5wKAja z<>xs@cP&lHVFW$`9C>*fJ_Z3>q0a$nOw#XO7f`3yJRR&@SpzCOb|o@Cj?wSUu&ejx z@<62cjN*pJ>knY#dsQXLIcZu9^mSW)CNFdT*Ed=zH#J$t$D6D>C@@k8Z3y0SM0%lc z%P{^4>0l?h9uOJa%je7;>Btq9s_C}tyw-e$hYMRbV>@;`w z2d%H0gy%s7Wc!t9rqc=M+Zy?7e}dY-W|qD5K=u<)MCkcH*R}$2)=~{gy=UR^aG==I zr_LL5j_QDPsdx!Zx@u+q*)8v4nBH}hb#ZaIQTm zINA5u6h9^9WNxo;k`26XJDEpqam$9;ImqcqEGCK5(z7LlfyDc9{Q=)B{$0}4dn;0J z>2;s_@qoLKK5&EEe<0Jd^SXz2o(|1#g$9&uZ(g!f*>S!(r|mUUv=|bYQRk0cbOWGC zAq2jHW4RA5v&IA&_#kAl;O~)Pfn23qi==|rNt4dwyoqFmNFi6>z|N;gn=*d^RIciJ z@{(Iw`pkGa=}G6&eFwYPE33zLRyHeIOEY4@EW|4}-6nczJgx~SnBBgo*B9M-zmW`u z_8K2+h^`97-ajkN=ia7hhbbmK;=D*Q^c*U$Ahtl3_0;8&S+&lfN8eQ*Qc2J6r!&Rl z*CXmKuI)XA@($odpl5e$0hCj&hw348O_yIq$K3mkZp!05=W#BQa2A&*LRFW)27$;r z3`5XAW!NO&mXc-0g;k~BH$;4?D^{qVMZDkO*>nLDF`;L2%5*=_1!Z_C zmu$S2VnV$e8Lv&U2}18Th$e$nSS^3bU4xwO`&2KSM|$D`jenj$cxbD30dOk(eHVum z$vq&~G9$-Zg7i2Jk$h~n2=5>vadn#&TL8{z}?>H?zO9NPp&>6-uUk% zzeNut*8nret!?_PMbbjPrXXs(PePVrKD-6d%UqfzNl95Zn)9to!*k zGzjCIOQxq7-Z;3<)ZX5qPi2B+(8)?j-#h2eVW;muPgt>~!=ixU)g=O+`81=*$R~Vjvsx$N?%@>F?4&p#-vQXPwFxY9 zmrXQs7PB=@9Q(k}3leY>r3$ZIbc>Uaulr_yaTUtaNjcoAmoTg{{1kx4fXq9)Sb!U5 zixF94sh2CN3t>3reMGqGfmTUDSA4AsoC?CbP6l^GH+q5?Uy%0Ll#-E1!2Amg^wx=m zox_DiNO6ux-%53zyeuJ+fwvj3_{P@E`@7ztt^sSR`DZHA%7W5X(X!$l>O*~7G+x9H z5BGAG%;|P%|G-FH3^RwXe30Dq&x|JhW~DjG(!%Sbz51Pgu~=DTlCZf{SDr8>Tucyj z)RSyc(a+-TG#Fv4-)vSGS7;Hzf2rIgBC>KlLi7`Kh>@&bR!+=|)J1Af-9#}J=~Ae% zJ)j#RYLB?g9+2@ikk}zU$B}t8{xG&=2d#x{CC<`6eZ<9Po(=dPm{1c*qV=e`QF2U& z>4k~G@ROCt{Y^8vOqq(*^9Q8%oj6>LS_$zgMqK zyq;4Mn1JK9jB4f8WRR}7jZ#Dv2p$hM6DNcF5&j3tnzp9O(S7aQNf1hC>E2xkUyU;# zoMfo`$H{=O>IIvg8P!$h8&s6c7h}H22W3ZkL>aSp8gZH$pUAIu7jJ;WoQ`}fFhb|l z-bZ2{;-{ikG@MA-WvF6j1CdjvStvGULmrPLcD4QH2ycay??Xgoqwv8nd3mA~o)x>L zj@RhS6T#5r;<(7vyYi__EiWfsbZL&Y!rrcPE+_|2=*iKw9<;M~4OH4xZK6D8cB-b* zGhH>!c)t|DEImn$+xG$N*Wx;_tJ7qWxL^+N#r6bQ_6vh1{{9e_%|(WqPp0tDdfF#~ zI!hzA8-eR9o3~N<%xrT%&VAn)j7}HmJt{kY^vtZC^QlIb0oKCxC%`VXJINBMdne=j zF`KFuyZ%B*3_dOqx#XGU4<;UEN^cn(3ytCFmO3iB4DJ zH0v~~CJZoytCl1HGjhe&{RcXau+H2U!7gW$#38-A;t zzCSSVYu#Ovf$MH;SjITe8OlPv0D?cL1+`FRy?d4QDGo;hwhfL*Ay-#UPNteV3^<&R zGx-d>n{MAiHI^1-7?0L0IfW#FXPYMVo)b?&*V2p^;FXQH?7X=%&Jd;6`Y>P4L7%NRzEwGKyY(K0f{3>&vPjj4W)O&bY$0oM%;|mIVF}67K`zqsn zG(0~Evbwa|wC}$G%vfX>odM6r_F$we+5Gj-(h4r(yxP05Rt}+^e#I_f3_PP|>;Dp* zf;jwTm*Sphe>`)S+1s6D>ot{A_!H|8Lu+pD2m231gG0{k%~FIujKC$pHo*`cmFy`{ zMmZ<2r9V(uP*d2*_QOrTf^c_!2X-J-Vb6sn`GTKhvRUSPaL}Tu$gpWxS6p0(j(dgw zr?|oHrme@Di_A~TfHWYNiSfT9_yJXdOl2!|54z*vrMT~7QWLXK3zgXHL7ffoh3Af* z-0IaYbp1JN7n_}pn$#OYGM6yTDNi#Q51s>EVwwtKZkgR@W2wBngpw!p1@O39B8Kxt zYgEO3-koB6or@Gaj%sZ+iWFF~?&`rjQ+TnT&@+VZF=D>zYVJU%yvJyzc1Xc;ito60 zH;Ag8B+mRJ@ierMcL*YK``O1tqP7XW4Bw~pnb!uLOi}2f&xQRJjy%D$2dcIQPsp5G z4B>R$?JAB*;M1esE!A3CYWmN<)pg=#S6d!=M{Y_g@e0u$W-b<1>~>-tm~HZ<>ve8- zMkrp9L4R^0$w`r!^r>E_YNVTFrf=OWtjz!J_1hN+#65J2Zl1DyCo)s+nKzX`$$;0% zGO#X4APvFY=s&=B@_iu`_(s=1aMhL zF5W+b(8AEnRKp7&&v|NE_4Z*?@GR@O=H%Q-Aep)Q~= zNx2SMUMU_$`1K`~)JV(DXNh~?(=&yx2q*q7Efc?xK#G8~=&FQS^Hp4VgRz8zgu|=A z52>81WAG+)UksjJXUW`SpRiIWzsOEjsntUHw2L!)BD{{<%rJJ%mx|Z}ubshH`}`5! z=nuG#`~o<=VdNOU^M`)*EmAW^=VBL``i2>ORXH92-Acd!510WpdEdrwZbOcpfjCuX z_INfXW~iAl%T2E7sT#p_G~f`N+y;&x;pr4B0~8VU)x+{t-D1*222-`DUxna7o;&7KM>qOWV}~T()7vAT0=rywa2ULMAS{^ zu52~#D>n?W9;7I+kVw(&sU4qqX}$a(sQYU}EDf*n7rNm(YgyM^(^~w8M+J;5Y+(`M z<&Pu+(iFJXhyxwundOnuroMr)OwxFj5tU2>h)sAV;dJ!7SA57$!<9mnl=;&-3aLd1 zXBd@F`yz9Ih)Qj(YP02Q<_@}syADQLNjodSnS{O{+CymH;O5+|gcS5fc4#hDk2Ni_ zQ~r4B7rW^@`qri zF=O;s+X>Pomi7bT!-mJa%-1V!K3MBT^4O8*sSbVH-%JQj@d~*dJFh#IP&4v*yx}BK z^N^;#Upvl@K4;s=6IrJ`mR=U!6!i-$TLSmB z`JwI;q}}%GKuFfPH{f>0S)@0guCHx1F3_swAJG9x!lN=_(!1czxKC_N=exV;yZT8J zMytox!%M)ffBvE3*>=CyU^>C6QuVm#TJ?7TPh13Z$D98dYbTtMrSj6dUxodj|4NEC zc)DcLsZiKAkbwTguR0cP^6++OUnlo`oGs{K7$1WjUZv1Z`^s*74aqU}H=tDBS4|UM zX!K)kr8?AlB)q<60f+o-yx$z)I3AlF9P5TNBj+uN9WYp%N7amvRYLWes#0b4IJz&1 zEhR{_JJ+p8umSUTO)`Z-xAU(Z9&uc2P21xokjfvEd)TBNF5SAk;Z?2_X5-1WUX9Uf z1Kt&MYCe;M^{bi6*B=Q^%@{c)>cQVn5%I4^-|Wi3o5tz}V`%O*cWfhpwk@3(x*I>{ zN|KArHuQ+DbQkImlm=FtLvJYGbHf=#i0SOp1OX+HB*Q6Kmf7mGD@^7gY2>Q5-Hc{h zh;3QzFZLBqbw);oN=ZZfoM6nKv6-QyR$I&3zO@Bw$g6cO8wNqnCh5JenM}EK;q=<6 zfmj=TYQ>v0XZogs$1Wms8QQ~3Y zWHGt|kEv(7ME0*LlF?sP(sPS%+^4=?SsGA_E-F%W{wAh!lgw%If0yj^GgbQ;Xd;Rz z8Si;t*~G`5ld-wi`#}-2xN5caa({eQ0Wm>VUP7*v0HGbVW6^Un$t(3f~ zLivd~tnNP3haTVbvD&;(i zROvlk=Cz8foAx5$LRr%Y7Ih!HLxSu79{g2dgRaR6d81is>k2mQW6=66vj;uG&Dh z;vQW<{E9atiNr<5S+`4g<52=hhdf@qW--UtO?1G2TxMD#ciM0BleYnV?ATBT$Wxq* z-2|y=MbGN&>LNPR_aC5ohu?r}C8s}GHa(B!$UoO}u1;bI0MOeIL%82tvH0NcOdP_C zmOfqcah|$Tg0@8#tP3m|ru7?Lrl%~wNcABj>A10m@-RJ^VzLl+4Y?SD2G*ohofTDV zxvb1gg~t4Fb4_OI_~;CuN^uS^=%8JTAeZIZ-(htepWyYuGgaPW20Kxj z`gr^{uO{8iy3>d{`VVx5`g^C7F_tZ#{sVGFM%ckGvsL-PdU$r`&*!^XduYzs(R!N@whJjW$$5a-+b~3CSw>)dx<>Dx@6XEvuaSaQA_L;vZTQO|9E9BEn6JoSvNZnmvV3x?JTy7c-e zO~>n|hwvuiQXGjB%$Y{avyNQ#n0@h;KU%&(NE-Oix`& zljSY1UV!iHfnfT&krcR`0j{yP3%kyQM*}@Rv}@h(p-Eg4e$oU@HhI5zj*%UF<_vn@ z*x3k=)+0SbI#*1bi9a;^JLu~&>3|fUs$Z;LW1sW(7$B6ytCcY7;~LrkYz{*9E_6qd zMThEp)1rN3V1Jo)4E?jL-}EFceg$C!9;(U8Smg{!QT6}~f{bgIF}4HHOT`h%X$%VZ zcs{k&s?3L$QA9^>{4=Moo5?AxzXG+EK|C*M2Ce_MYk}z6XgB-9@Wdvvq*^RMB=O-) z*To?Tl<@wrbqLSTXW_@okqtsZlqaI%N{Knv!;;`}`Vx(g}F)A4_{PRj(HW8Jd2qzV^Q_4eC9zPX~8(w7}m) ze%MeQv;o4oL8M5faZ0m(WmYsUm|}$PglY^>^VBN9_8FBABNjm|dNPdQ2EY`*bsTON z_ayt=b&Z2_I2kAZDm7uDgd=d>2T3y;+UaucXti|oa2*v6E=V@W4#JcEHL=3E8m5&9 z9=VvqD<<^d(o)fG^MK{L8>=2sBfj9=tn1REi!&Puk8N7C1=z*G-VFZU!_DW=S%nw;f?1Qz-1k~q-hMuqR40y_S^T;q^T<47z@pp1Ijd_LBo>&-d~zYxB;Z113jijm(9nfy7D$ObwoK4Kv|@| zc-aP~-~GrTn>{^cr#%HmrLhQnG#u@J#GJje(~&%GP7v|F>KUN!4BmJ(A)+a0BEBaY zv!C%!X_h)D*SKeifk-w6dDOVs2Mp5OCxN#9jUim5Z|R-;oGY14cplTD z(UNdnY4i_8igLH_C-1ydA{+_)HXy{#bU6yfkm4f znrL-7z}}UT^@@HEnXy__3=^6ZVIB%P?#5~-A`(>WyeZ+v&f$7by#tr)5BPVSl)@Op z(6^d@zCs;-^yE24$87Drr0iXn)+#~3Oou2W;B($jvO7N7&?JziDP)NdW|mXHnB=<5 zSxEzyU;Sw#e&4(sk(fk%@5zX%Z1rC;)@x5CdLfaY`xBpXS+R?y#R9} z6TP#BI^FA10W!5(ZT1aW;({A0u)}zmOu7|uNq&cP6c8x8aT9+#TKd=_N6CqtR(Cu6 zak-R&J$-U>n@Vv9-2S3mqsE*W&;su=vx|wzQ&9kXNR9ov6 zHvAPqCVhF`H|6U4#MuNy9>3B57N)I^jHZ6mjHq!1wS8$diF(BHs>65Yd@NVjA=lDQ zJc6hoqoDz`mSd(<{|9|E;PU+9^J>4H56|&tM1aWf2x_vxGxQg_=4Zc!kIdfr*9nlC z__wwh$_sg+Cf1Hz1=qH`>C*4EPTrAty496+) zD75~<(Q=vrA0}q>9#FPhy|m9JHTdpRL7JtEaZ}8k`!o73hPOwE=qj=PxQ{qN?>YDq zboM?+ZzV6h4CNn!o|4yl3zU$JR&FlTzy)x|4{mBDPc>&Ia3yjCu^pU~=vP_NpEI#a zweWQemV|@*^a|@7S3_ajHN;(0^kuf)2Bb@BI5co8ON{QFo#AK!Lp*G=V$jnxJu?$b z58a3}so!StDC7Z2?oEkmG5e60l~mIdod%5pkd-ZvY!PM{stU2z%tJ<9@KOoG%S8GPwSb4!x|>ZKTkM z(}4{=wnFxOu9aolDoKFBwbFVNO6pIbb?8RyF)~dHzBe2h&(j6F%3e+T#`2QJZ^;FK zlHiEPEdH{uLWI3P3$e4L4>P-Y595f^E9aDIe~z^KuMiAA2W~ryH>h0 z%8D-nI>eB)w!s4=%P%=46XT?hu9pM?CQ>>GeHS-;6as(jTVsDj5}T^ch47r~h?qF! zUndAM_vUi~j|0Y;oQ+g9I4Rv_c9{^xpk+=tcU#l_4K>9I#mZDkd}Qe z&Sih)BK>oRDdiF0#^?}e-Q7v6R`LgC=kA^SgfF_erD^F11h=&Qst<`+FDFpaN#E8y zYi<$$c2fI{`2b8R*=2yrW8f3cs4~G~+GD#s169=-Su#p8xE@9skQlAil@8OiefOUV z1eIlgN!H7QW+qd9n3r1#<~MDQa#D|!QH3y)zLICuf+0-C7)LTDq;?V3yI1S6$i%>l z08KO32QrpbQypff+ez)$wwBzLt&CmZ_(DRT4}B*G-v@Yn z137oh0F-Vrngv7I5AR%hCMmoB;nAjY#VGxfpN|VHUNLpnLYN6xI!@GZ@lzLR=sZ0^ znpWgDj?=VyqW$w}#T)CpX!OZ1>>dm?rjg6a3>3O6hAgLk&@eaYO}HezvX1LkNns)S z^-MDC2%jLfn5h)VNGJ6`o`1py4Y!k9fp7xZkOdMU2dghVsUsiqyF`$S_wGo3F)P>^ zbCYs;TH>6c8MAD>uHhhf_=p zSbO%!cbhtd2L(KPo_>Ep_N9``HuRAWxi23Es`EQ`uFt2M*mi%1OF&N1lA7kexxJO@ zhQ;kY^oJ>#Fo8MjPvRp8CpogH!{flg4@Ki+^siu!zPP|EhRK7Ypk>8R3 z;xAf_nV*-c`SDi?zh&;5SSRqfspX4WO=FNMv>m}%5z)$0mm9Zc%l<|msD(zYL@3UK zwL_d96Ob0s8=(FJb&Ap*35hiO8K2DO?dpd&gK`^gf{AT2Mn6xXDAQFGnwF#lp|xwt zzV$%7g{UpF=lHOiL{RQB$5kU$Fdr;pN!#&<*5{5F`4lhscT%>F%V;n4b*E4EFLe6j zk&6rh&55#;5Ruvh%f_CSmz)HC*sIS=oN(SI+H9fcE#Yxyj?mTsfT9a+DP}Z?kuB@ z{fcmEF6v8=XhFPK_1%GA(E}_wG%eb!lxF7F|L=`Yh$QwFQZ>^WysMW$w$rm~>0r{c z>q440zXG8@V;H8AN1r5h#5Tdf{LbEZL_qujHGq}=J3P4C6A z(Do50mg-S6t!d&_8kMRL0`pNcIl29`y|4H~VW<2egQJfP)*#bEIjI=_9B~eNL2y*YL6ZtM;iF6t6awgG*5jL;dE>B)UHG#B>tND)9SuKGE0WzZ&RZ#y2Y6s6fE%Rc zwBk5&JcO~RwtA%M*#-{8j}z_oh|;__`y1u+TQ`bMENAbCg#X^Z#U$ z^D}%VlCf09kun&R6?rm}L58jPAChEbBz=#ka7<`|dKqL%bBWbeq{X?kzS!8-NX({s znnG2x^ZQ1NqcP~n}0WJgCr zEYFMT(Z9dZW#TID)E3_SMA7ZhewrTblp3Jl+ByD#E>`gt%qdlfU)P7QqDRgE_D=~aTsCfwn(1#g{psB?s?NrG7sc@gP`>y@4e&PcA#Kn16?=*Mg0NF`g5OScaZ0Uov zkh)378WzWsN$EcEkDLy0WmY~pMDpzG6em*V{v#uVgS~z(@{My4eoFoJ7}+8}TJGDj zTX~c>sMH8ovb81Xd1>NvW&l4kj$aT*3?>N+N(8k+TuG0Stvg|qh=q*u4BD(bU1%k5 zTN9}bR`(TyC}&Sz>{@<62(!aeFQ>YmG!ye_;+2W?*XaQ<&R&bxz)*A~Bq`Nu_JOZu zbz3iz?8xU#mNk1<5Fu-(NOyR6fz{8HvklA*3iVxQ^Qlk!r+{=J+M1F<(L($gzC;Y} zU<=Y|A73oPTFUvWq`=L<>V*~BRk^FLa6mi5?fX2a{orV6tK7>)kN!VmZxY$oS5h$-Fk%}~aYB&ovF8rv#5KO7w zTk8{0KW$%dm(NsbKK?lc&&)#9PY0)q?eYuo)zPO$jk)9CAEBlo&-cv~*PXH9FKwdo zq21K@H`@F;8QDZ37z{hjtw!AX4lX_eXQ2q;uMS>A5jcB&f6IVWM!!sVfq!#4>Qixr6e^OzJBTM@COc@Dv z_ns+vAXR1drt!^ELL1G_Bp*|$Mc&R2Vs#*^Zme-5nCt|;Y~D*qDs`GXQxkqXl_BE& zu5C*4+}l$^!mQj<3g%FMX%3hqv7{Q<&`O^kSOmr_#jP^uskEr~stctr5oL^XKaF9z zGBLiL-jh`G3VqL4>c=Qqm-p3GicnV5?33{uwE0V#{jKjl8*KJ{YC)Iw>z597mD&Mt zzcL1>5V7yL-vHUa7PnqVq&gZ1CH&t*0ZL&i2|A8B*y5|c%V*$wc5({I(61;-EIU~Q z1hi2T{gMAbd-UICYr3lJV9WEHYrvp7v^SH+$`L~MMZ(`eheK^}9aY`dM>64>s9Q4C zEFjc^RvP~}zgD0OAW)bE2;|_32>m@Hwlej9*yO?LmuuFPk^w8RuwjG%3ow`CL!cur4l?e-pJ_oZyEsRHe?tj9~@Hf%lhW5zw`Y8MgXbOVAFN(_MINYRC*n9dw^OT2N6t@(UJr~M{zkX_ z2hxpQd|jNLVuFZTaB}ewtA9Vg1n?xxCvvAnFqW^_rtsQZckdr0r;vf*eg zVxin`2v$oo(x{=3%a}$OC=w~Lgc6eSi*F7;Z3v(7YAIf{UXAPpptG`PFzp^Hf~NNF zz=fr_k0fGt8g-U&B!$WzKo%Ep*jh;Om)`A>j98XYkh5;;^uPwUim{3XRCSN5%#wUe zqw?uxr1`!N6(H8Xcs5t)b#c7`relE@*>E>!I&IY>?Xjh%fzLQ(%}+Enqn|&Ycm;$@ zeqdRjyi-F_0y>zVJ3=oG0*Or=siN)Tyq!f6&vy79on$Hnm`5rF5~38|%}jiJ$cB?f zg6w^x;A2#S@WUFQD1hf{nwA30ZEGDN=cT*+R8@$lhHof_-*WZi@-b4mxr>DM`&(;% z?u96eih8O$Mo=G-KtzMzX`94P1FkEuD@q-*Q662 zG(2+JAyS;G7SSY-g3g5d`)l|)sKZ9W)k!b0TC=H4p@Y$m1bA?(xVWd>WrPqSLU+p3 z=%)-BBp}05I(OW_pA)2PVmS_9X}C0WXsV?cOf)j=SkQ-*bMp(>=1xmerSriYtB2_s zh5Cz>OR3ru6%~3P3Qq98HVaIZUjpV`4nig1;>o`FV(K#Tn%{|n|JxMvHlcAXi>j)d zxWLb?nuO*a3fCNCX|2Ag2Mo^PwjRjOVch(9mGqxl`Ex>usi*3@R=PwPF@6-+PgGBlho9afbi}>TH>)RfbKY4$DK5f8$dQJ{oaC$D>8EqkN z+SbN_eV&q(?qqw&Z&8$I2eX;KUc({Vqza)$wu3{ulrRpCw6wGpulMK=)7|{rUe-26HgGxsh|kh1XNgOWU@2k=z>SiW5sk8B-j39n!MzZe|6PajDtiZbrrz}o&zY5LV+ zO-6(0ynGWv(Bn-ww&ZQZkw)b6)D7+|8~IUoy=uIybedJA4Ht<7J~aNq*WuId?VoJC=k=9;gqmNh;asj4dd zMj!h9IB&V}oye9=gGL^&CqAY}gea}9*HIC>pFjEKw|&WM)f9SWBp9C~p&CXjKkz>} zu_2lvA3L3wAQ8?^;QrQmbXdmv&jsCUM%vDgveQf#`Z))RiQvwyr>fc;LXv4vR%;u#!}{+{&Gw@IEa+Q_b(f=1=#%$LaK zDiVipNI4OzIxp{5&M}D>Dh;7UwBcAq74Tx->&`_KrVk9;-VGyCcJA7|C<=cM zOXKk(1%n8Eyx+uqrxD{Qbc)YLOEynPoaA`2db}sWdjPF4$m_uEDIk;8(>*}0RrUTO#(rloJi;`QPmJ~PRIFj$QA~K3 zjg!%8gquLrC@t=}VOpL7>!HJ%A3ysq>;6=4SK?i}nvIFw-TJ7NezWbQurO7M zDO=}-k0TO$dBGF+C<~??n@#4&vvZ=mpbh7Ue*8TEX^q_v#`K!;pG!~my7e^8`8beN zVIN(-;)R+g`*RnkgXVIzQ;kqZO4ujQ!oogrADkw!f7`B3+P}Ztfu2VRl`tz*fqPsv zU%d7GOVEKma1)r&W*mdvj_uo&u8srYWceAO^co846rC}NGWh?$@&D%xV5sE`1ngoj+lGYw zbwxi`mo1#3OUv_R^1LO!IQj-I#ya@ilAwIeFQ4`#raT^cI^_QdxbfW8GDvR1l)L&c zdU*RZ?j!h5Uwr0UAU=rWPdWP!1jwYYiPLmE!7~b$ZN>!d>qcbkxVwylE3^v5Q+TltkYz5&4b~lR!*=B1o{ce_FC}38V&C{<{q(Yw^-WJPWsldTE3E>>3XO}G85AEbZMce5Bm+Ev`F@-oU21;G6 z%d>gq5$Q%G7JDjr6A#Kc_A!VQ;+-u2;@?}yU(S?oo8ud}WliIJaz;nUlvf1i)84CZ zAT`bazvG}x#!1IC4~?S)(%e2b-v(mP2Z^4=-(V$=hImMm|Bh_Dv!D#Ya?nP9McPSk zi9LQJUy$s*(n4!Cm}!9l$phxa&%71lN}-d31Z?Xv-jFoTNOI=QMcM&F1wV4R0-qov z8)3|im?My%t{-=c)02~D;SuhMg8xEeZoBdT9$;FCLW}*tzmJWo){vMB6QkjCdbaaI zh4_otzY`5Uw5pTvoQVW(qN-z^EM26uvk{*+==fKDbgF2bdJ?pEper#$xj!$-&y`Ky zRK6git^yOySlZBS>V}4cz^^PZ}mt})6eD=mC zKPZ3jp@f&nix~}OzKz7$TAsCEXNWDK)_?e0WyDL32B|+WVgJ*$T=Vom{^HVgjGtb4 z>PgHx;k0kmaWvM%QIKX1-<^HhYo9`7gdp!_hBKQp`lUAFTd$lE#0M=&AbzWUI3 zp;qR@BuZ1&rM{T{vQp}rzY^CkRY*_CRRp*+Ts6uST;Jo_X3 zQsBarf4RPp#M6^^$^qQH8bMlTM#z}nbCbbZ6~+&_p2klb=Yig?yk;dMmQHnzZ$#nD zOQsC~Tvd2)hE_I>k5Uddwq5&-f`Xa z*?l;UkE8wGbCpBjRQ8T9$w|>`J^&4qKVe?l=>WLoZ5*BpUq$dR`!bVGu$sa5|V42V9k5A1s$Wmr94@|Ye>OoDS# zj+;GQtVo)Q`v#BFkYmtxE;R}NRK?mjTJOQ&T=R#KiF9~6nMjA#Q@*7NmqUD@%N~es zJ5yjQQTcxuJIk=9;y>(^jcwKW@Q*oWh5vu%qcy zVYvoRg`SHw_~T_q#nIS}3`J!uOY-fUcSESh9ypHs9B(vLp8e<~o4i`VU|$yAAE)R~ zMdh#M(szqoJc0Wkt8oY&4^5VH4pCRFdg%}7#Y z1ByO4sjh5f0%gAhS(vh_=Nb5jQHJ$^fB0Qu^-eg-Y#vSTao}@DXT9nKonjiFEWu%u zC!6iMo*ZwrSSSf?KfMYfGARTq-g7^CzX)2k!Vhd|VpV}wSk8<~_=6pHhAiegwOMcL z3ewuCmSZ*u&_-8Y3d0^1qec@Mxzjb<@s3QcmPh{@aDun49I_k2)Ybhk8ko zbZeZ+W(#bMQW1J-9Y^()h6?X8mbB|HUCv?grZG|$#GX)x$RId?@rj80Z+O>A7m3Q6 z1Oz=+~F`-uWMY@_VeHy6}d}Ot|(w|X@n&CY2~d6)q%g;&T}XIzoLZy zCs#n^Fh+{m=sx1ig>@S%pjt48V|fLvVl>$SP|2W1dz;(>6m@lDtP0#HGdY2|-Ydbz zJ(vvK`U{`3uxG?D5Rc`z%GWKiiog>jomapcG=>xk857!7gB-(Wac{0-Jtv1(0S8r1 zQT)Sgx6}4NRDt9dB&d$G=b}R|>4y~IVQ0SKpPFEM(0Z;*Ul@^(_mwnEgqtj|mNCV( zj|FVcB3M6*Ffq~caBnO#6D`xSS14bRg^q>_udE=cbuj3_!^ra*iiPzp0);@5Zectn zmB5Vh*3@I?S1FgiH7nSFbahz{mS%bB8BJ`qt!aM z^~z+kNvE^$im@+GvG!W=NO}Mu)a?vDZX7;^Q8J^$nd`Nvzy?zkCwUu}M>5dAO!JUbRJhj|9hvyS;Ph_^JH2G%VZm* zd?W0%z@_>;0amG0Y_uKZEi;_GPt;(2t-$~jk%~}D@&20A(JCmy0&+aEms<^%MwiqP ziydzWxUfp(cT0=*^iWF00cbbk@nX^JyYA%1zwh|90D4~~r?7h~U(3XEwdD7vQi=gU zvX~_Qs{yp4!^%cA8JYkFr%+lGxHU__?IB*hbPPFvpkH5EBht>Tqxbj=?{VuzvLTn+ zS^?%M1s_ibDo5HiP)O~mfzIdE`#K#W4j)QTlWLu=!w=8uw@@I>-hqC}sH$P474@8| zto~{X<%5vsksU9Uh+A#%;Mb<~>6ug*)-g@B9^T5DdCn{KfE&|&ckVj;tBGsluropx z1nK}5P*kWiL#cC=E#o=oDm@X)c?f%B((oE*OXrLXXC}yx;VHWww8W|(05d$W*&w!$2o^{ZiZv3I9A2>} z3>aJYo_mU&i$Iqc)C7woU!(1~*OxU|FHbAU**A+y1h6SFNvNGv+FY$U8 z3Gq?cc8X|2%B5pA+7Mn%R?hsDH|flT0RTd2(mt_!pTR7Ok`bc`wR77C*t}6+xmaEt z6~U8*`H!>+)48&)jT;A<9#QzQi?!$|i>2^YI3=h@NBnwb%u!@o#R0V|^)`I`610`lYSysW~!@`yxQDcf7`6NI-`3jP3NaHbpg zvRD{T68Nns_*EXdwEsE))^-n7G9K*6ZeVu1(Z*sgW_3Rt^^s3lv=%>!l9?S^)}(1V zZQVYos~0$aN?eMg3C-5w-Lhy=OV}q#?qGTs%0bI|LQ=fRkexYN@g{s7xqSV?+7n)o z^bX(|kt<%&{$?+ip3D&QkhL|PF?)@4smn_GgZjwfa$+;t!g{x*t?wBNoOJ8-vzL@C zM<%!6l$cnaZD>@{yR6sGn7XA+>qvh{lBG`md|miUK{q5QTMF`856s=WM_U1X3`Edg zQwb2Ke)TL-{t*ii#c^0sPp|hm8PYvqjdXp8uF7>eN^vz#E*C;OJ;RD)0m8JN; z)l8tXBdT{N$;@2>3Hs9%PO%Ay zu8U{I>q#u--tm&YCFC)lCG1EX|JvnoOjyq#`X@856ot$&;vn}QXqNPI4=7Fi{%I2(1Bn#Udl$ujz+dFDhboz(}S_wD5=-H+d#2Gtl*?bpg2thyydY zAV+Ahxg0ZVdBIft?AN8GoC>nrJDyV|WPI{9G82Ty)x5*+k{4K^^iL_^=T~=+86r98 zOE&W9^x$Jth0xUfY-iQn@tpFqJA_lv$4ieNLAo+0L$ji zb=^*Dhg{X_x^eC~I@8SC`^v9Yqv}ek@=qG%qu=rq1VyptR_J$juz}!KkwiILzwqd> z`|f#+1{Pe*xm3(#^Gw%SBsQA)3c7bQK?KF)XMJk~aan^|r1iyT`EEy@L&Ws2fH)Db z>|JDpJavqi@-lr87D?<-`ZMB zmnYXMw+DS4*29YBiVFCJYB-L-NobsC-iu&1fHuPVyH)-OUp|3HqpvTo5B`C+HV$o~ zW5qUiG=f6L(^t`HF6%Cbg5Nz-ePb5+{K)W+{(p}D|Eczqp_Ul1*a$_o6=X0*`L5HU z1A9U>;?A(E-$(R!0;icDkzFpM8^zFtqNWua8bE=jWkP##(>#(+6LsQy53o zUK3aCzIWmOJc7|rUD^+rO8p0FBE6C=J(-NRH=J&h!Ab{X{zLWdD6``5a8(|+TN%-e zdWz6oN#G!)pNu&?6q`$3L0HL2G=PeV$OMnOYIA_Fri|+AP#4T2DU;&Gxn@I}mMiI_zae)7*2$%Rw5wccY|6q2SXaGkz{|^{I%ARvj|s-#|t(ZudAdT)k4qn zfl5WIAnu$=Aw4J@LsBR?MVFK^jL@o_e2%>Ex68;V(wLR}wSrK?>L1GIbG?H+ey{je zais1L*3R&D8x`-vAz)n^zeld%7upK;fr;PyJL)XjB%IEpv)ptDH=P_Y)fAQ2gUkxN zt_pbkKqY>%E=&+b6RYYQBT9aytef@Ss)sMTgDEqvD>I3XA%*6_d=Mx4$eqL=xVnDi2shrTLOfN+I7)+kVvNA@9mp@U{sJE z5TtP zrL>MRJYk#N5T~k-Hg`+Kr=_*x7Y4g_(8l4NB(E+egaCd;w~ce&ye8Q>j_gbI!BiG$ zEUon~S&zvGIG#C+fn?~g1|%J~-#rR&RC#SCO7Z;khIeaKqayB-Bz@>&BYH#~vYT@| z$|yJg7BDywB}xUHHgvyv3b!2Jc%D}Tc^I)+wf$GqbIIPxEJm-1^j%q;6TWrcUDo}U zCM17hhX&2#clL;ebUN)B;(7KD7I8SQW>JWz%D2FPICpc`Wc?1We*u*fP z)vyfEoDUjLD$NiId>XbidL$nCMCjb7S07er4Caioo`j-`a9iG0;zA1OvG_`;Zhi`g zW#tS=3xDKN6?5t*fYvX7p4r6D1AL>d-)t|XnI!m%eUpLUfRi2dsq@~y@50JkeqMNLj}w}|aNL)Cy0 zI88G0048iX!@nZ>5o~$b#uY?TNLSs1S`U(Kvv%kI2NLb?Wolu47;aM$-tm|}%$2sv`$ib~QGz)5rqV0wQOk4aBc`=epZrnV?^M>&Bz?eW zoO)e~BS#!@d)`vRiYl^x>$auBv~L&CtBi2ZfHsv2Ngp2ZvWY_@5OJM*kci3!UUPK7 zoEW7ngw6SG))8^&s{i0H@@2vJws8m>>FAM62B(57bJqD%J4pBG27s+pdztkzPm@c`0+09CXZ=jMKa!JjaZWKfMSrC~%0?!=n~RAJyQ_;>mSPMzSR@w)St zWzDrbR4=OT1m)p2eQqO4nfQ*}#?~^%&WNsK&rAON-3P!@#PQVCx;AS3q=8t4bh){m z=i@lSlRTeebE>?>+5dg=BnV8!TgYcQ#K6I;WUK329)vOQARu%=@?1F1bKeAHn{sfs zO%o}Xlp78@Q$vJL6?!CL%_6eG*X@^r1;FIX@ed>_CiLV8^raa##jV;A)Z%|Z!|iLj zoq|Wjf_}h!(o`U`T6txyo0g;SmpQ`J6fOr*oD@qj7j?>VtI0BaFNy6%vu@8dn2j%9 zVs)n~1HfJH6LIHPRsiI(((0|8j7lpC%`=Ay9@iRIf{D{CS1L`o8Y~3>qB45mzVi&&^3@r6l6OM?Y6W19?r}bnvO0Su99sF0Y5A zydp+aLIh9+l<%k23d=>jCr$$Qx|%HZ_Ml!#L?isCyMzyJ80vliRfPo-Y_YOXWVNNw!9{sYyEGkIjmRBIM0}?FmDIcSGw~QYK&a)UbJwC{Pi=Qv@?F%5*i+~2 zI)H^xH{@-F5G~;~5z)7UK?U*QWuaXIU#|UQVSRKwQdW=mTw5X;)>Z#7G|S2lRO=2S z*PJ~p@}(RP8m#P;Jp7@xKCbLR@{C(nUdpTz0uA7mzurK*355>(*7iM+Cz=7%(r~8i z3KKWz?2E>rRySL7zq;VJ9n~}-$`MDl!9@8iicTE>d-ZPm%;6|Z-eK}FgmuJ1JB9uf1vN4qKK%-TX;=B1<2}GX;^7tHRa1R z^S}pJ4_F5Q?j)i?&b@~H?CjK7 z=UE&ljUKHPzvI@Bcp>K%ut{MU1`9qdE_{Xn4nw9%Bu4@ijufow`o3M=YnqF3CLNr$ z>GmR#a3YCTSy47NPTP$WR0;QeV=D6J|3KrpQN?Q&cc7snX0VbyhtFgTqS6`69NJv!C+_yL)PXY~3-FpRLM=h$1G5@igO}>z? z60%k5rG0?amkL1peDfRZLn@S-{G2?dFU1oGaw*a;vaX=F>xiR!@CNsOMa@Z)-i2lb z--m^?VpkAb5%~B`J&;bHE_b}+P`h`?o7%N#QOOoHf4Q>SNesbUM9li(ZE%ip{jEy* z0w_5~X_)J0Tzk)U&k|K`z_n4=Zx)+RQjp2~55WSO6>q(3Gg?LF7FMw)#|W_vuzWJK zJjRuWs1qsOgb{}U=`}tEvC*>a$VljiPxANaF~{-BL;>IWvjAi8=Pca2N?jk^SPmw5 zXI2zM5NmtFy0Uu!6Yx4|wP+jv+D`Zesg0VyJbXguns?I5t89}W=JPyP2iwgEVuL=& zLe~w_k5FGkM`}-LP(Q@xFIt&Z_x)L!=b_u*{%|}YAXh-~6)TW!SW87~g!Owf@)Pwc z`d*{boU{TFG(?mtn}{@1jJO;35(lI7MrTi?%lo^jOo`hR)zH3Ay2x)(L&A4O)0YTR)OoYueIaAL`>q8HRHOHITCjj;GK{wtZ)0IO2 zZaJ|<0nQ5NY$ZgXJR5BcR1G{cet9@27W*~oW9@TA1>JW|@v_7p1<3`=>a0wCm_&O1 z!a&v=kEr5!fC|MXjx>%Fip*cGW6izT-(7Qgeh>OECVcq<(;2%$DGsZ5;>4@7sOzCca{iNl#MJPN}X{cKz zPWwQ`Ixcv3>KU;SwRmLd1n;LCe!m+F*3wGP=thcn{z`{iP=|p%PEs!Wgn6u0Bppjp zR)T=Z^}FdpvW&e51kKGLC#?_KMfXBWF={4;A?7WizriY?7H&Ob!pK)@ecxMi1A&Y> zyS~*!uy!|n(9FV&RNX+gAL>Kj4dbCwvCKT-B1HirxVAbpn!$a9LBGyQ(bf0mcCfNH z?D<$ErtKz=q%3es{S@qsg!>Dg#b_l2x@wzq!ILoUvI=5rpm`? zj^rjiUSp&v~#C5U(D6MX~-f`*mJ9p`l z+^FEz)w~u;^}CE-asdQ#TT@kqW?9P>TVx=4gSEVxUD3Hop z9B?#GRF^r0e)sj zRnQ+npD!X5%+%VFi~9Akpiqdfjyh`7;etFJm^m55S;fC-G zRYX<#*(OKyi>e=RhB(qFBK__W_SE`%&^5(spl-5hXm(*c1g6M?necK~@GS-xR1@3K zd>milO8^vq9mWt0CzW+E>$|&NI;Wu9^$^|t<(R!l9qLEp>~`VqKrJVhRjvCEs&D+m znQQw=+Hq=^ArnTLp1reEq-0^9Yf7E_D|(fILr=_tmh=Jl6c^Qx1|TgUe%&q>E1=<1 zS)Tgspr0%a9Qi44BABwSxvQI)>PtAPXKeIo93NZ8rMx~HkI>+xJoDNt`_wGX z;(;f@K%t|237{K!`k=R^?c1%2iQ+%0{k(gRZ^2*fU7>$@!+MY$;^+ zEz`h9b&u7%|0tqX)eNz(?@Yf~aO~r0I!3jh42bSVTtvU2lCZJRHNP6owKL-RzFvb+ zPz%PiLQ?alkL!y_i;KSNV|`qK>W7(@WOaJIzHLDwf!pV@t=xv)Fmyej3_#5_IZdZ% z>bGhgG#88e;5J+Lf{VG`3%5qdM8YjQNA`w}KR0)hGU`Y;D7_X{d1c?Vz;!SA6zMB09`^PhnKqFn>+h6wjy71% zDq!>d+M~VLOK-)t%I2|`7}cEc`;XGoTvAdnnvOl?m@Ay@??elHy=7i^S*dpbqvUuQ ze+)Za`l8970OC4=iYjPT*LXrz@8%mQfZn{^k|H4)Ov@JAqLP*x&eqkEqTkTevpal3 zlO`oQImIYda(@!!BeQ^aLZJp{(t%iZGrQVOtV9^$q%9z=F?5n%D=S{A?^_hyVq06DfmL!?S5rx5JCdy9yF5|Ro>VlgK@OqC zOlcWC8AD~$a}c|4=n~c+DN9f~lY0WCJcw#4dfs=EvlG_(4^%{2`Zh=Y*4>f^3VGdX zLjsq!Xon^k<-_1gaa8cP&SxTmGYUGnuwIa2H4i&5IE?Ud zsFlu9xH&S6AFhQHl|BI56?e~vqDt@~Z34MtIk`XEuRqwH-H*2?*dysgRb>_AsWB80 zPf))}C}gwhp;^pT+=~V3=n6bayolt7sC4}e2z0vckTE@>$h+Wx;Csd6EZ0bU-z6>4 zlq_C09b6IqLSHmS$m9j9riie76r{IsWo9^&Oa;f8k*@xLbwsN1Nyxp{5yy=tOn-RK zT@vC9CFjg1?OUxQe)v-sgB03^B)dP*fm^gSllcK<=i`VfMhg5W=JF?_77C<&0uiqV6Ll-L^DLc|;+7uFlsB(Q@hO?o%Bh<_Y zeo;i`)BZAf?GKg{rSg;CFwH}qoeuCm;84rQII^eFvXj~&JwVSk>{d5nKKLF1m{^|h zMB(e{^dT0A40wr95`~QpLnV}{^|0&pF6Y}hae5SHbLaHiX@V30`{cCov;1ES!t&<1 z`6t@}k6JsAXuF7$egh8oS!r%7|HG2O2{Ri#p*(APoz4LqKr`p04wBDb zVBG)#<6Qu6i;LEFp3nr85<%7IGZ*4&ya&BzThM3ic0hmcH^5=6>gk;jrK~um;Kp3LiV@cTOzgUKFyw->MpM zeq#dr5&Onc|BJre-IM~^t8g|APKq~7jD#{C(%e@bX7AbZK@@g`rb0qtT^*crchpAP z6hf1QhSNUUGxA{nthvD$Sy`$j+5 z|4u;l_7lp+MiEo~^?c#%sFPf(Bu!iNK~qj0NvKa=iUK_Y!%#HJzVnki5@>UemHPO@GsbaSayR*v}an7Ge z5!^fl-Z%=Tz&;V}K0)nzufXmIhwZum*XZE7N+S~7JNL@<_BP6beF zIJTFl;akXy-yH6q6J?uqL!yXqjGVf@l{cldguv30BW~9P22rdT|3Ci|H|A4oFaIUZZS8cNO!po+Hs9mG@Ev_P>+HJobID71-~W^qFpJU z^@=N4S9k$1buytMCP!{(mJrLwA9SW_fPtZ{&T?kV|6c11hskQ)Z_Bqt2T=vRHx`Tn zg;Tsrn?HCjEdGID_d&n^HU+8^ZqP4hUF^o6lE(=PEfM0W4hL6Zf&D%0JzH`LQg^++ z&r-=)`KJWEYEVaA!o9|d+BU~0%r6$C;D3v_>IX+@Vwo9h++^7yJ?LEN;0+&wK!s&Q z_X4oX20!!`Xh{coB(7!v+qE`nAH1xfg{@KN*r?2upznB#ENFTxQib z`!sE3MAL`#8ZWy+bV6H;v*;*W1leU`FZ8@!k-au}5(E)zizh>2*O9Sm!Uhi3g#P3f zDy=G@JC9L4N==m9cN3v4&)n~lOL3GYM1^8=(6dNirHh~ai0ZMD# zA%4xijVA+-G*bmcZPcaFKE|j^bF5g(ff9v!X=Ptrp`3tuKlo}L!f^-VoLl;tAdT=J=v2n% zyL3oXJs8qd*o1Gz8c;`DPp zJ_gsbqV4HN1a84VyG$2qiq-QTdb-$ADZVj4asoG{xjyhd+)8-1lz8ct3azSK)hFYQO5F&r;f6yk<1uj$ESb+DOm7g-GqmmVb~ z$MvA@BV9}8w*p_{`TVlCkQ*8)1*JV@jMB;#QC@^G zQ#^=oKEJy>OL(Brl6lKMYOjA-QQJ^Z z`IUYfoJCH!l&}VT$UjaN&)zJ<`4#${pjw^g-o$c}+k6>fOaoCGQ4#WP_%%}Ssduob z8)5KevMwEg`jd17=mhZEBb5D*!C}O~aAcbBap`#@1t#zFOYZAEf!X)j2f^y$obu?JqN4{DAOm(Kx_wPiV&(=jI7Ut}`Q7{4DZG-eZY+Q6(wNt&L?nipk`#!nsfU#3x9G^e^G?lgV6f*%Q(a%lmFy>( zRu2%FaQ`T;biK!~`JC5$Qt7MaZB@I&->4~w$`q-+$x@zj8<==Jk)A@R>ChQa9ZRia zmGncnl%0#+E?QKI!tnty$^g><*~%Llp{5)d9o=|Pz>yrn#6rWwfMHa$t0zU9y_o0j z@_!Op-jyK$xz&_aDEXm$gb<{Hyz){m`?aGK{88J?m` z8LpiE2deY%a`hqO@Bb<~fNQE(<>TYNn4k^!NK95VFe{Y&uC)RPQTQN1-qp8e@v)pa(c zzjE{leaKtLLrguONF&oq)AsOmd-CtA^=;{D~4|*4Ba)@tx@F!!sQ6_)Zsf4~*%kN|zS$?7(0M-x86yudAO3WRPoAy}PPF}pg z23-(jHgLWaag9Ox_`nLUJS4cu;WeUXw%`92FIhV+){(hwMf?6d-*QeXt6=F>T#`oh z&%7Z3>eI$e8AMVUAh0SG?KMoegJc~7*`G!1McwmVwr#B_Q^iR5%Ky%L={gLUuYznl z;Knen_w`PQ;C0?sokrbAkaUSVl;wqkTZ$F|Ih`=8U5!RxT?sHKt9rMaEP5B+Cm5j?9DP=}QJv z30GT-wq1(~Yi$%Zj->H^Bj?5L{QcqQrJ$Y5YA&83OC`p+7o!1qkCb5K(&RWOiq!d{Txkcx7N5|(Fu=P=DRm39bapA21(QsW=={C_ z>YT=*6M52J@nIwt@+7J4jHGA>K&IfN(izQj!NvKCFM#YB0AC|x0IWu-{B(V~=V$MP ztZ-(nBxc|#eJ#rckfpxaP5TG>EbA`PXTXG8!7~mCUg;FCTth`6rnE|jc*$v5qE)LF za4_3`jF+MeQji>H%}kQ{23Cq%L_0aImunZ`c?{YPMXkuj3rU>?jl z%%1jPGK}PA4Q*vQX78lUxsMZZky z<~5}XZjAy}$G+;1rP+i&!^MYL^34OMoXO|IdiuwRfsN6csgmo!oai>B%G+OTE^Dy< z8L+=am&k|}4BQhnOmvwjvt|emT{WbsG@9JjZN<6QOfcl6L@>=f=ba1oXaDAd)xo4N zq1(r&F2fY9vSoQ_`m7z#R(^BUg%;$MswD-C!wI88sqfI_IP9rCz(G?u)!8x1;tUf8 z-ODbh&U%3hir}DH#-TN!6kA*mSH&r+A}Mw8>-MN#nxeUD^N}Lk zy!Vx;WME4bm_uZ(t_D|=Pu|)0pUJ(ofJ=ahS7qXTtr309D`g-57mKJ*DUeT|$sV`b z=(9Wro!$Z@i^^b&$zrAFCNx>oO@#dJ*+1xYa9g{y2c?-U@F0MQWOhxX*7s!?&;vxt?% zx7L0s&IfCA&Mu-Hg!c^0I&xd%QL(+GdXi3uI-izi{v}@~m@VU@8Z$XfKzzBz^+;Ww zUTwz!gU+Yc8m!4W40N=kRm>T{^bg)A=*kfEs*%Lh!Q=Db2H;eOsElx^dqC>k|k9 zSJ_fW$NErXT5X8UbN6~_Ygw}f=IZ|}0e|udT)?wSr#Vu6pf`tA3>*t#K+ieZ(!MZA zT(_fRv@yN(WWQFsC6MeGM63CX$A2wF;_xSG@7FQz?^YN+`{Zat%x%IAxdYgY9&V10 z*LthXNM^2VO&7!l+)ZZb$(F`LcCx3Y;o4o#vwEYCydWOhtRVtJ(n@9@3!;|3xmxY6 zc*#~q^RZEN#cGu?6*dbekJ`R}&_qU4@^?ho`-GH$;d!=9+cDYtZRq&r0YEs!*|72Y z?pXQ0kSg8wug^gBbzK{u0!-+wv7)bqdQ2KY8G^~(UE^nVzI1k2*8xQdrMFvJi$y;J6yi9JFz||#Ui~m`HjDp(9eWF(Q!GBTf@(PfMtlY z!p@&kP7kilT~M^ys>_V#^}Kb;^K|j?ag7b-llTV$R>3hM-}1rY{Sd z_#C4T)X1jst=ZUR;GTg4-p2dg9>86|ZDQ9k=&_TQu0ZK@g#NBGfdqBE8@_u!X&ZB; zZ~&8=Xsl$z)LvOuTj?)jPqMwVMDO1Q=aUHp04cWS z71sZ9QZ=vE&fuEx7kpTcQ&}D@WL|c;DFj3i{4xzo``{Z)4&&N;J*M*Y)<2MTzL@OK zFU+U2cO!-cZ|xlj2ALm`=+AS3YQ!Mxay)nwY-X#8-kKIYc?*}dgXv4-Jpt#Rc_|rw z4tOf!XS}|ez#htiVy5`mU{WbkYs4;vb2&xZmHYxIIiYx$?8!Y_x1!9srdJC^RaJL4 zk<58?)?`7iltVP33U5`e`FDnu4psPI@1I}P*wOOip3^O6kpG&x-Gb}CFhU2p#G)dX3wx$&p#&*Uf z)xm-Hc+aV>_KH;_td8*O%Id0vG9{&QPrdtBeJ$qoQ<{DC4&Imk<{<*F3C@(dx({CT z!2@(BshAb7wOnasMElz6*$8)M&sLBdB9QwpsAWb!DQ&s;LR5o+1IntO!o@n0HM;Qu z{k@lhJO+|H7;$&pbp28V;PqE}hvrqQw@j8FlI={@(p|}*suV^#s&R09fMlh!_YYNo z!1NTVPR(=QVA5P{9r=pB6Y{#VGQ{edKoz9dv_V2XGy$T@`U@W2ebb`yoD^0L3dm5`P1t+a)!09scg4K0JbG+7+QKL zFGgNcY6kGi`p@r ze^Bq+NYze>%PgDgyQ^CPN3J-{@ziBwA`_xyYdd9>i_3cfaWFn?BUBuz>ZQ3gX}lU` z=O-Nmm?VH-cZiGqfZr&*t^_vxwKJi2G0^{Uf4#`IX^Mi@6rRQHTJ~PPy#5;AU+4L5 zcuVJJ`7WfZm)OMUq`*UmkG&}!Ece+n3i|8ip8dX1@+LN!^T@upOuYbongbZ*&fy`w zxgUk^`Ciw?qjV_WM-&kq^Ru)5H)ZhJX$|{V zlWz#b8`Ce7eDW>Q$cqQztZF@@Q;{CBEmoYz;Ffb5 z`4!~&v9(_r?}MUg_wg(NnF)GV!;^VnAsYZA^bL?IP5G@;JNz)x&FWLR3;~rS=9Awe z$_6F(wi)_lfrE?I#-|QeI9&y<7zI?x*T47isfbLVdb#;_mL3>JRIQ+hI@mb<;O?lw z@uf*EbH|!F*=w$Z$Jc|)0CJVN zYRrxJ7JYwY4Pg-PtsQmFsC4W%LP%Q3_!G!)e$30uDp0E(o+Y0S0qHTD1vRCCXa?kY zVimIkm;_zRlt+%d>gJZpbr<_PP=&mrTh!@wHG_gKA=69WfUW>ilLvmucTHe9@R#N> zbf)H4qIc9aJtiL(5`ejhkWnmVO??}GXFysA9rswF5vQCr|A>N^AI+Skv8L(Aj`EZJ zpA-h>9mU6o7ZewE&tsYSpeM@99KF=ls^xDEsTg5xYfOH|1M+k%xN!p-C44|6dE4kK z>#UhKIvr*(Y~+=ing>Gkgn2Aol~J-uG}j*rloq?4pqc|zDkWHMMMqP~w}GLvgc0Ku zeL2Rr<>}GSW+vm)@Hp}odd&zBR5FSt09I~>W_&%K@G|#EPfMX|Veu!b^+cI2A&nIZ z&l@#;TjDt7)))Q%7dW~bfyUQ6qkxR$dG zD;%P*mR^lY_!i?EEBJ^)OoDo8yKrv-kM^`;1y@MXoL40gpXCY|v+;`x<*N}L$Gc0fL0uxv0E*60-iYGq-FN*BoMfuOS(@S+ ze;jE4Vr^MiQ^cskgEIg=gKG))&wSHB2gfgb<~K$K-+Qd0<)sr?URXcL%5}_3<2S4k ze%yKJX9AAoLP;;t=A(%_FYXcWE~0fQX~UAcQa|IdA&$ff5IQ|hU3dkSiyi1n{|14Xc@$HL|3qYAnK7X z&42}O8Ha#Pdi)h7d87K_P`9=VEL-)x#H$bptD=Y<%fi{W@p;w(PHx{Gp^qZVQOqZrNZ*?Gq2lhOSKhnEN`&LJAf7by6nsbb$WVte)=vQ*?bmC!IG(3zrK^`v7?ZRevU|$7}KTS{%d9<@`4JCcmgWtYLr!@>s`i!%Y1pAzj zPKGV3_hG%Fr#rlxn`ZL0pf}0C84Et(<@Fdw)qu?t zI=pLV|7Qg;aBpLVR(hg_AhmzHqS^ap}}-dI=9xT4GdJn^WYaX1=TRH&u%q#KrX}-~?5`9hB-B z9lzv?0f0KH9kEzju(lOIqw z5v8x!A>6jzeddQ@+NZ57WUP6AS4N^I!rjqqf{EVMPba7PRO}yU*3_2flQ0YcMKyg; zc6bnL)`{*3od>BWBLn=_)_L5DOS>gW3z7;EMBemhx3Ba6A z`iXNS%9xwEdx8?PNl4N=m!GcY>Z@Y4qnCdXJ9E9~NytjjvTinSt_DU>wdg-7oceWl zdIjLew~<7Ck5%I-ZdOUn^v_#f6>tbezFj%QC?HJ=*?e}7C-1&#GZn+V=aGV!ixtUw=H+-CF+d(Q7(LtRnI>1iXotY+sGMjhfD ze!lDvQ~8$VdX)7(EvIcuyhxvDQE}N;*P{-lrC}G*p3?YuMfxU`@ao1n)**J`=OOG!NBQNT~uZ?H*?s+0-O*k*Co zR7D|N_WEL>??((*K|KolOZS5JyDqzCM?xfM0lc=d&;!J0w-~za##CzF{=Dvxay&ac z&*muZ#1k1L?9@a4{O_>h^~~s=${}oUCSvgSn!Ik>x-*KNWZ}{pVKV-kWq`m+EoZ@i zJYOr6ab@VR0oA8&C`7NEE?PM8!*#9f{8nd4pdxDTR$FxF`AmM#Xh~5S4l6>FE3j0V z(nK^S$M)&+}IecMDd>1tbwO-+Nb_ zL&qq6=Rw1g<0)$Qt*qOk4b@~92(b^H=l;ynRwWIQiD=*k??x(^f+&6XH;fO7RFwu5v#m@8xU~(%Q z&qO<3{;EiN)Tn<2jn} zi#TCb3!A;x{o(~Z{^d@pz8Zz||607@%z3$|JAnI*`qmQNk?Xnj&<)7y*1H<>y6FB@ z9ubl6?COQZcCR2b_I~0pA2DO3YWG^HZc-1KC$06@QvQKLPwnGx-#2;jn?XpnkKDR8 z|7Bo}zEt0GiO=fM!Eb+*RmsZ(@L{n zd|)OxaR42_>>%27d9p$G>rw@#u=y0LwlwDz<-VA*b^VqTNc%0b8SNuW6X2r8hsUTM z%~M_Ks|ds*r|o(L(A$d7+P0XK;3QZx=U3@$ z_PY}!s#XCh7Rl>^{}0aIGAQc!Z}(ri8>yvt>7|htSb8Z}6r`lVMLGpRVkv2sMnIPo zlv#w`!9{7Qd*zvnXOC2wM20dwjdRZ>-uTb8MeMzNVVTZ{*FZ<2axNl6*poC=w)#gpKNF z?fH;KzOKSnXUNZN_1GnJ<<9yAb&_-+Y#$$=I1i5o+K+xNhE=OEC#FMF|4otKs}>|H;_?>SQ#Rm$s0y{*piBP76NCE)={Mx&yb) z-EhsMad@h4B#iqg(}0F)*)Gg6c~&a@1N~M~%FSIgW4R;8QO6WYw*#?DArjdvO4S-Q z>e_TA-M6Hv^SOH?4$mk%5*d9Z)^EO;CLV7N5G+Pr^CKw40 zi!UeXM#)PRklexgIZ;`gL#-2ld(93rmp8h1@CL?L*mEMwk{kV#vj@MtS2y&8c8{m; zBLCWI+(my=)bS--0<1xjQDFZ2is$J}^yYG_ukXq$ICTuv`IkBJ#B&>UTV5-b%De+P{p?@GzKU?0|YJsh)_JMgk*qqjHtxS7h7P4 zlMu`7sro|}B!BKpZ1F7c`#H8LbI8$g-2_@#s(q`>Fm$PAw0{=_1m zi=7B(l~327&@qWIx|!btSD@P5tP{+I96ee%uD2!YBm5nlG*knAmc{e>WY3x+>d7$H zN$&9Y^xUBr8^_-{90XN26!?KpQMWVjY+(;hL^l)y9lPPpE=iv|kN&B_F{AA5Bdh|u zE3B&RF9C$j=@Jeme#g&~sx}c99KcP#WrpbFL-Ms7&c>Fqgf;GX`e^W?P_hFzjo%%m zf+s)wG^$wYG5HUkP0c?Emt$91-OO9f<*Xh}rWD1vwo=kpwcBk7ON~Tu#jf?EMby6* z5-s?E(R;te!{gAZ;qLrUw41hl!@)*I&LrpB3v+{`|EkAmAv_6x7$IAIKbDEOolrMCwP&!iXhXX zz(LUdgPl7*j4|W{;EWB6j6Rg7FR#PyBES*PiN-kl2Zp$?4NT4{p2haw!#oM|=tR5U zS*v82Z2se9aI06%ujcM5gLEyZp(2zhM8|nCy-O59TD_E$JWV z`{$vNC9nn+YTm61M1>4nz5(_LzV-h=3z7@*eHT?`-60{U(RHgy`^Z05u4Hh}V81^F z#gx-L3C#z#&JC_DHH)*#6&hH7RpdhQ$AR_ zn{7J(`Z$uroEMh9j!6TS z+oD=94IhZLuZ!0c-JzLixvWpb&!-QQHLcW>{d~WDm^--$6XqY>b$$uuxs)6zA+}iZ z(qDcg4v)d*uTb$5G4O?m*U|zTM`~Uzj=O8)?n2O`bt8%KDC2zN_pAcse_7_E=f2|V z*9u87E-vP)rMPC|r1a%C-hy2b6*IZX4-a~)z`%#5u;N7Ac@ z>Vb9tS$V$w=Eppw;4nJc0wp}-2sqt=!z6cZ8fiWBaCMaE;V;3$bckA1n-76n7 z+RhLHmE0GOU3))89QuoJ@fohG&!h#Lo5GB5Jp&)Jm`dE~?YSl)?npSHNU@3R7uHsQ z9(n_3exe}^@jYYNOwL3DQ~-D<`~&{U(8Ph}NG?aMN*#mn%x0d?veOh=bJX{xl9zK+ z8KX!$m`j~dvWB=iK~^2z2;$JNFBR>?uOnQuAvQW9jQTGT4C}TcSZFsY@5iTrYV?l?4J|QcQCBF8$ zx60q4jT7L2`{+}WFHD_sj5-g;h@p}n31|!(_nvU-^SJvxs+89e3`h_q6A$OJNeg_> zT@lT;R>af7M>FIYFu!7Trjk-A?pyMTHO?sXM0vQd6+Lu6JO@Ame_9h zGgN&`lHOp$MK}bqZGXj`bL%d!dM6 z+vwSTz(vxdu)GSd8@|}rSJWN-Z1_IjuODn@K$S-G=P6h=$HqQyjRq3O$(lhJ_+|PE z|1{68;nzID##%BW-p9~_S<_2H+>z#@tvQSHVcySgQd@uv*K>|FYhm%JLTBewInM9l zyb0yQX#4&m$v5*FO|?OC^qH(ef;vMw1W}9W%tLNb9rG$~D& zHz*;ep-~dPjX7Yn|Ihjtryh74I@(@S$F{m;&LA+c3tmxzXDf8z`PF%d) zrz0fDRbJ?j>;N!{)sjA-NiH$`fEcKaFG07v*8pF7iiGvZ$ay|Xt-upvjqQ5(NY(Kdr_9F~v?URTH&LEt9Fb-WHI zCEsxUz7|$W=*S{vl(YZHn>Yd#-!2)uZ)kMxk*NO2U9m)CV1aTM82@Kx# z#(?T*A>`!8q^g&8>IHsapHgCRn!fD0_1z+pLdD=YZk;z#v@&wfPLQ<^YzTtpiX?&8 zmWJ_e+IoXZzBI*kW217*hhYy5Yw*HM^sAetKMVbT`)Cr#nYj>_4trSNg-l*OX(^9Dnmp$J)_54Iif$?qW^sZ z{y#9=|7)R4dLfX>Vm315V+%Qjc*2(~Q1D9*n)(>o%zhoFDqnWhtnJ|WKS=-yUR0?l zf3EU}pONu2!?kXA3URW77n1~9aD(lMK92f!J-}*o%otT1)fY7$nzjKLAo=9#Z}Ll2 zKZECWhD8mM_A1Z8R_F&d8%Y@%Y*HPeO#^jr2GL&P^*=o7{`R^1&SoVZVgvtTg04Ml zYFQrBtYk_M`{@^zX1NCjn%S3Os@6um)pvC((_9=t6({rFq}rJL zXg+Yxr|X(kpagxe^KHeRk6yTCJ540)J3=6H9;*hwMD?fXYo2$>apcM}q|3um4f#o` z+hlH^dzN(jxl3mOhosZNCdJe}sn=OHpwFeP>$SOpv;5z)z~lGdAIEq}y~}bmiG5@x z?W&w&!IMoo(&{fxe&?O|rAH`wqp2B({miZXI5}O?+stA|N(DURVw1T6+MebAo?>_`J znzV=!X=Pr+vIp&5 zb8zlnLsk)7qT@pzdspI$d>R3YS0t(jqp8DIjx!O6p_IzN8)&IiNs{qHhu7Vq`90@(XtUQwj613y%?2|5OZJ4yj%%%= zC?Io*_t2>TEQOPA-FrsU_U%qtu!TO?i-*u0)c{`lplRDv4)fp=(SEQ9p$?AL>RdUj zJB2KMcr(a(aL|QKrfIZ=+X^IE+fD$dg;iMQj4b(-D?NXMX(zonXd^|8MY+sU9D3y^-dg*Sk_&3Wn zNEEL`)B`*3!RX|Z?~XP^a7Qcn)Y|R4LbWvPwszX;q&P z*qX2)l<2&2AqF%NZKm=W7llB#2``ru`B6-)Co^Q7|Faj&bQO{jTGm(p7FJi2DZ;cvo~`sh;8W z^Xre{A@>IFgK$YqSk`S10>Q0m4!=@@)fLFAHqcpS-b53}Vq_(R~ruUe(g} zEMN-#b%BX)u$pZ@G_~um0RpzQWE{zX*B?kYwi2#)Arm#`%1ZD3lktoOC1{wba%tl_ z6IS_Ree!7XQPyjWG9}fEpJ5RxL%9=wHz#6!OLYq*`IgLui$U!wO)o&AKze*E*(%-n zyPGe-I@cd?h#)dS`+w(;C!pL+tjJKKzN}9^cTSE?^-d#Mt!?5bQ2&?p@4xw`(Rj~@ z6jFl?3vfEkK+20{Z{ux&(!qP?##-CeYAxNx3kDQy*Yjk^^PKA!WY0hTB}JRdYw1?z zY%u?UxA7LFwr_jF-P6Q$p{!85Um#X6Da+0_a5BnHlS(fYn$z>O;TA8Yr!4?iH4(4N zJtJ+mw|lju*;M)A*Xz{m`#tk7!8@80>Po^O>byRFZz z)->_NlDrZ#Oq~0*&W%r*(v>KlnC1fQ(saFN8RkD4$=bz#Os78^ITO=mL%%Wf6I|B8 zVgv=%w0-50`ChY8jW(NO2w)QO%G}V@mq&0a9)8u^;)3cCEDAD%$t{}TKp#Cu$xxou znI>X7)-_x55HT^wMg>Qef1s@5Ps|+KApYe@Y+G3K@kN{x_}3dqQuNs|#BLQ1<_ONJ zF5>>aR2#Ij2e02cH`RYB^+~+7vvb@0|5IH0ZuxUmt_@?w^Y(i{&n5i5 zBUd-I>sdb7DUUr9Y4FW|MF`1}^%=e^P!D_=4QMdV`oEa6okY}*Z;Z(7UY)XhcJjd} z3TvO8I92jhdr7(q* zICNs?j@Q=D*AgKzVBe|9nxKvQ?gdupc9Hc0c~V;)j>W$821}iTVJc65xQb%`6vdkT z&&uYN$VK=}ztuU}6UsIx)tSKL820T>;U#&vx2XIBQOi)_H^}G>WfBDhe(8+vK`!g2}O52sW zv_}IeWR?=zT7*hUwr*cT7-7Y|i(Gevl?s23&~=?q&IDOviD!5SOgAhh-b{yuO#-i3IRzo?A+ix+jDDTUzr{n=2YTi-b9 zhm3A?hIJ;rcjf8qeK>>#6@v2!#3YabHjISGq_>H%jx;h6B5+D2sHy1i#hIcdkWo>B1QLA?ZX*{fJg!p1-oC1text>3dX zgiPtJ26@+QnSL{lm1XoMWq7CLhI}g03`c^;?pzl8WPRn^GP%PODG<3zj|VlI8iPMH z31$HbtabJ#bXYinvA?pJRDHM6tN$=?9{q{d^7@&~+c{CoG;Vuochuc`06vepbW6a2 zR^uKos13LN#ds2k#S6Pf{t{8_u*f}=J->(RjQl>$P|-W`LT{r%kkQF5{#Lhy){>{k z-I{H&Ou0+dl{VQIF?Kn{ZB|k`1HiLB*RbwLU-&1|k8(VKZmP%q33)K)Qzn3$tp7Ct zQ)$3B_+xQA0447iqi_te>~$%Pi^aN`b-kFMM<5nM9rj=}ot^;c^iqQ>q1CY&C&!{D zZ!^Bw+Tq~`H5J-Ih>$9N)x_ai+N~L8%PaZDvV13X+E`?gP11; zoK2-2Kj+OA5Q>M^t1N=?0l3Gd2(X@LN3uj?yR;bRQ`R*Ns^-@z#M}OxC)84c(Qgqi5=Ov*j~!sl40>Y@Qj`~5^c z4U4^eT{N!5NR-W)?mAG)U%+3}CTzyiG*NjQA$HlpW-Vh&o-sFKUwkX=H^aMUK!gGl zgo#ukSXx7bW`8QOS@7)3bW}?XX+DdkCzFj5r#=e{K=r<&q(YVd0~rmjRa{DrWk$>| z5llsUFvO_tt%?T#bG$Y>5pYA=Oo3Oi%1*E}xg+<-=f0u?CgJD8sBb&Oj zHpwq0`t4IFbv2;BpTD-AAi^p` z8- z#Q_zVq(rVd0h8Kce#<9EIVK|Ty}Ve2-!+idxxkl4g<7m0T2r`|fMY)~nkSg5{PF6! ziuw@k8TUGV5PhY95Oj4pa6<4&li^mGB7<{SHkeOvO&8ad{KG;I3po28Cn3nEg}a$f zS^myozolv_C}m|qvJ*Jym6$H5ke2)^IT8lF8s{MIo-pw$FjBBzYVsX))Pl!9N#>Q% zySIdlGimF)<2ZtuTr29)h-!`8;EL!dUsn<|C}-9mL4CximGd==;}Vf z=Er^3)XvbW{7^}F?yAi6MpKx7(>Xbx&WHAk^@}g|`mNZgfsEr=(yg_@jb~Qqfbj`c zQ{`JYlEj7bT8TS4q_h%?kiYHQFi&s0a^gapiVSO1|6&Ud3aJl`suu);YuYS%d-EJx-O{Ee~N!~-RB~Z%hLTlH8B4$YuB&cGpWPq+ImLn%M{_;&W?SI#2GG> z7Qa&TI@!aW!z$(0v|SQbH8k8Ae6T3GN5axc?7UgSQ!>J8KUmyt03^~!6H|Tz?UYJo ziNUq`ohGsxMGQ};N|#ZPXfx?L>WwyV!BZ~}k57t7iH0XJNvE>lcrE6UHVMEk6l;Sz7$6 z`P!J|^iDW4y?>bYmjM-4(-{a?p#>w&N&D_>dq_}RQc_hi4}AQrZd#t03XPm$-EAiN%giF%kvGNu zU7FbutbBavBl#gRTa>=2W7rm@?#$NPOG7 zW-O_A=2UXPGkV&gA6F!P$t0_P)ouVD>2m;eG#O3esz|5bnm=)4{OPK zaW@&gmu&G)EtgWiIp#M&m?1VBDNq+R8t-;)L}9S?$lG7Ma}DTH{(-t8j_zJLTk_z# zQ6GjjxQNx9hI=E14J|%0@Z4ZpFx?er+(-55lKB7eg7H6P>Nmoa&5H&A4vbR#RhNCA z={Q_8Ty8o_y1T2uBVByOodsSSPGRm}bsh}$3F4?|=g~k3$hkr2DIWMXubrJLFte(u zj7yL+OeSgxzi70HgZh$%Mn4aniVh7@S<$`g(foEk5}|Ts6&)7K%Fk*m15qSZ!5mOi zSf92sb0_fR#XYpATNY?7m`h5RYa<<8HlX5+&$bn@ObgO?l1)nrTt)_eN1KR!a6sgy zv#-!B2uEjDO)sK#W)n=stELG6yrnBG<;Ax!+z+HvDB2^?yeo%V9N3h@nLGBRQ%w=~ zyUJc;wgH`qnWSne&o9e7`aaEfSamB3Z|0(NJ5VD7mbi?-V9^NHpB28Ai!#OUT z9;a+!ynVQF~;liQWNndV65yqBn;#Ooza zaHe=~=Ik;F?-nm?l92mUV{g1Vda-O<%W6Iv$WdzN(8o25S5s;6O24)SbJ0Dj6d=dh ztdm>le9KIKb%?lEDnjGyNYllEG&Jwe&`rx_%YT+csK3)S%_zOmr@u_;4@fx7SV*D> z2LZJOokBlnWvFzCArpzjgSZBkb77Y0Bly;1_HVaV_N&@O(^`ES{?t@<-vvP6wpR!@ zGC%1dUG5`aB2#7CC1FWhRHJ5Z@)$!PpzOIxu4=9SYlYM=ARDZp)zZ9v6DoqkS(3Z} z5%@@k?!ggkuarh!$v^#E*mg(ma*mSDZ&3&8zkYY&C4%*3-QtG=?t;MPX{N^`sTR^x z0hFU!hS-M;nT}*&yA_mb!N5d*x{Rvj(ODVo3W&^;+);m#gC=8?Lny;x1OiCBi)!qF z?-wj<3wQFqFw%a(SLhKS5vhw$oRbwT$xROe<~6?-HM<*#-M%KH9+i>G!H7;$&UE&I zF|ZmZeJ#bCH zeJf-PgFYUTZt?Xf*H?}(js%i$gmy!c5I(6Ody^DDTCCM6b#WRyd1Y`DdgNEr3x!tf zFE)EW_ZV}nNRUhfbPdmqsuCFu~%UR8MLsPD(kcQ(oO)R9AL$53b z4SwN4YrQMGYG8ni>B!%Z=W8^#J!7UzP$*nq-(nqzT`t=6t#6c$(-nN6CMdj>d%JiQ z68be+dl~C^r=<-D0U+PFab>rFIx@G#Zc=8jEwzcb*lK|3yMn zvLG5hkuQx^5!Xh~LT6GK=b%K-I@7S)!6Ug3nU!tbEu?H^NrXZyw^ z$0i&yB9SKM2SBg;OrmG4Xry}@A9EVXiBWdnddd+gr!Y-P5ss{tC#p*wZKNXls|0m& zVFf&FHSh|~5Jvft>|m_(LqFrW<8E+4l3OPkJYH2Y>Qw`+VOpY-kTt1YP%i)0+Oh#9 zh0Ny93p#M*<)wM{A)DMoL7<^%O$mR%7-nMB`b$083^(>5NtlJCv%_Yu9@j~1v?JmC z;SKfukAuw;8m&ae2#)`>&a-D*UNAQH;GgNLIhwDA_>~|;yB?&`5tm3OvR!}bU1mA* z7B}X67yN_+%1xLqCT_$Nb-h(!b$9bidRtpD~?Ot5v2fq zyLZ{UPsvT=E@eu7b&ELc1_<;PgFM#9HztP=Dbae3@bX5!S)=l-0Fo}9uHrK(Wl~0P z`Iz*Z9wy(@&TXj10aP-L;=ovx9tuh?^Po&3tTrk2bw>-sY-Rj5hZ3dgd+FB^Y-<_X zTB4CK#fIZX$u~?h(R|c3%$X2+oQ0w1Bg8D+=NZxolT|-iM?l3{CXH00qATip&$OBS ziYbFPc>rq9XINm7?j?81Ouw4N)&zP-`%s>vNZkDj|Cq5bOg zpK;JZUIkmOZ7zh=Vio^H)wlk}elCjYqi~MGH1tX3v(?5(Q#m|GqG`5o$7JXe8Nk+t z73Al3u2B-#9%2cpe&1Rf`B(s)yBBa=YbN*m@i4vLW5SK)FJ5`)%}*>QWkXj9oYhVmdfe30`5RaQeR`D{$H*?| z#(*9k9If%B;tF8F#zy}T9CA6H)3L$vTQa;@Nper`SvbaKZUOSgpMLA?DlbkFxF5PB zgrQHy<&-^yWiq*89dB|d#znD^Di)Ue#jN}@a!mIb!>Y`Mk+>i;GZt4+>O=X@-p{C1 zuVLOSj&6^*c|#jM&?j$vAC2}S0g_tVLe%_hEsZ%&J`A#~G7|&=_Eg8qE+I0}2Z0_P zK2c7*(IF4g4Qc7SKT`IMMYnOd&#rkW^r2{o9cqeo)I`of0LQ%Km6(q zVElME(8o2N(X!<$;MC?Wzmg#bAi2Kf9Vvw<2`dov#wo~yP=K-#@lof2M0zPjZQe2X zk9p5i+7DdMitdQRWh|MvEVh^i;N+vlzgtchjPL$NKHPZv%TI~Zfkhg3wxH4Hvf<^0 zl5iO8864q*qI~IVdd|TS4+Z&0;R|;Uv6UxX_LpI~@f`ALw-%C-MHHfE&;p?3s&l(! zirZV#k2$ipg+l6uLIa34;Zq2VP-34nq~FgEANb&?*mP9r37~u*- z-pNft%XLq;;Hd~r+L0bZuLW)Lju-xcI_&R{>MD>eYFTX!MiX{JHvNX_G|Tf>Y^mwb*xS}vfS*6F~=>)Va%-@ zUaMQScalgf1;pJ0SU|Kz!V)qv#Q9=*dlVxXf{#-o#-ivh3haEze%yQnM2kS#nYlZc z_+7HsDBrIA1QX-`=#h_u4|z6_XYfHvJ*y0LXULG0ZY1-QywQ~N#_$(sqY3C2{eh*W ziEsHSBhZ2j)b0PbSqVVzvD2#3{QZ-}owEnuW8Ali@~;9}Z+XHY9M14w>u=RWsgdrp zo+!bmR${rVv}_5?s6{FnML%gok1k^gIDfSgx zEC1;-_z)mV@B;H&oqaNX@gQPrKoFEt&_bTsYW67Y$=`)`5@IQNTnnJZ{LbyYV^ElK zSMuay@44JGj}>+KFbNklc^CY?LxY#br1X&_oZc|V7t|WK_W4-+m)tGORi2Smfz~Q7 zqtTLc%KobzJl^=kavbCEF_UJ!FN3%2kt>09M!NZ8q)O70JI~^bCA}P}9hMO8;JFl? zzjBPYSs9I=m3JD?Bgvavh)iD7UEp1En3y|I{ZAP}(fy2i!#6+zM`3wl5IY4*fSf(P zXW?MCS;!lJH0UJeGrdQ?&5kwH6Gb`G26oL*l37s%tNIYpO%rB{bk=GBcq}XA`{Xf+fE>or-O&L zSD*O0u!Q?~ucmW$SI-)+KYAiPIhj1}=yV8TWXB6{ItD;#KGl%!tIlCl%JgT<*05Yh zZy3qj_|LILoIYh^U`tyKi8DN7#|J>s#6i;~sce)}(A~@PMd3Tv*Vj?!XttbmdLm82 zlD`#dU6>dNDw!oRJc2Ww{@@>HxX26_T%bu%|Aoa+Zs;V4I{O8FI4385_tqlX!Q0M& znjQC@iIW_m9BB?P6Vd~}+=CNErWnY%q$lx#lE7E^P~s7yM_RY=GSW>wxS1tk=tgje z{SY8oFjbATWD%rZgo7)gDIWlKUlh?`-sb0WQ>ZJ8sYYjOfwkRW^wWH{i!p9mxe9o= zsiLc`(R@5(tyS_v@GB zs1_VU7_o{Mn7sBEwu`k`-Yh7J4lRRIaew6qY|;yj z91BO(A4mOf0s#VWvp+Al{>HdHA!iJc*yn1+cGH9uSt8xa-y=1cS$Hbr1z0q-eZ~0n zdt+D^GpAp@XOvY9XU&+fEOkp{Ugh)%X-5ocIfmnby`L5Q&vT)lo|$52zP=Xe#d^MD z0bLsz!m2%KLr}Zom;Cv40>v$hr8*1Kr>6j~{m+-bM}2=}EF(O^=YxOz+AX$qB&rqf zxgH^Cb)(%*!Q$(ivZGH@b#--JwcA4cIxg?G8>&v>Lb&x*^Z%=a0L9>cA5Z>ALrt{0 zJB`}jb~o_s=noDDXTAGV%s;;eh@ppdzx*7IP3nh;44$K=&YO!!`>T;iu4B2hN1~C8J9Xtoh^!v7R(_h zeV9t?NDAEgGYYnEj1m%Z1MU9&_0o)NZ_yyrhnjcjuvkozl+o*HzNU}no%^@XNiNXB zLfz>FFjl`?<;0a7@2vf62cxZ=5mhd{=j`w6iJM-KdA;WzQQqoj6@>FYdC+-C1X5h~ z#bOs28I|6&IZ=$XkTcgqLfrtK3b0e8M9k~N$i?Ic=Mcx3wPo}#avjy3;|+!)5kUM9 zbI>X%lBN#=GWoE)4*0yaPu3ce9Y!8R-0Oxa;BcpH07uy&Bq^0~Xc5+rBl~rK!9Crx zWeRQJf{=1-cxsnU90!|Kru#5tmqMzgema?I784J2jLL^ke=Fnlaz*_MX!R-IDzVbk zK?87`-uZz3k6ll8y=p*blQ5qhe8@W@Aak&vkV5@Nj@_9z7LvVWG&P65 zjR!x`sU)v<2>f%e>+2)&AQdju?UAVT)^$PM4(DuB37wmc_;DMgXPn|Z$>9cb01Nrs z=c5)V@g2WuR-b`f31#SL!+`fM2?`|OyQ!)NoC5qE_Xq@5k{>zqg@~}oFNETCVsXa} zT7#2XMD{vK)|zxZc$>Pc{v63KBRuv6wC?RdIo|`GSmwT9%J+INTvgjZ<75lZYnm$M zLJB>Ce+eksSaT7PI0o{*_U4N?!fv@{_d;bNIiHv5s^JkceUF}_AkDhiYG>U$HSQpb zUCHNlz?1!?%hoye7*~=)Zf^F_dXAt13ofd8o;Bm_;&Mz z5Tw+d(~toPAc8!nKOKVf(Uw`#8!JqHB&66@mzS3JU(##6Ta=WiIV94;0VgzWRhu|{ z=d{FkC)5=8upmOuCNfQ&gVWjvsdk2dbjDi*EKW^_;jGv#e^s>eu)Uj}*QTy&`0)IY zt+99N2c-W2XG+Ex7*st=sFFf=n)+r6ZFAv9d|aVwoSnY@i-`W7cR9Lt$@@7<%1KSj zVu`jhAk@Zc<2N?5V2oBrzl21{8U~^-=^<6#dro@_UR7dOG+iw(cuz$(dosOk zkOGqo#q0Jx>>WYyl5FbIfLj?w9NY`QXi3i_xWb@)$0cXk=2fv1bVxgfYjQ@YhV0(v zwT)K4pg-x*aRi_v?12IF+GR0!ztT68Xj-Av5gYB3HfkK)4_AQh=baX%a%+Bn>l?S8 ztZJ#VeyDqeoPF%QFLoDrw@g_um1J9b9D<}EG1J+7j$U^Q-Pb$rXX`}EH+ z3GZvodM>(1~v7kj_tFrruMq~q78Y}Ga;nT~I=DhRnL>8DTqgIt~b5P};3 zY2p95Q~-5lQh{n%CXTklc(Ak*f?q@imq*hI4qoxxO>IXyfAT#z%RCpJUk4QYUs!n{ zU<%bjY7PZ2CJ~mk#cG(wh25V@XsrpiCpPD&VMRlz*__oZ(3m{MWz@PM47dO29rcmlpxg%-Uf{kxi?!x*7Nm^Pw z4|r&8G|@TLCA*Cge%R>SG#FE9<{qYJKm}8sPJDn9;k4&*<7=a-4#a*_#q_Zaf6OkG zs$}SWcWG2|vZzoM6t301wlT-?H zLFa}YQ)1rQVICmNd@8@;+N#S;)}89rH}!wLog2jT)LWMt6b8 zv^_9UQ(ZanX-bUY5=hEDr51ilsf;v9$jUZZO8ZTJduEw~;>YQJ6q^D_`-GnpAD-jr0QA=`0 zFv28HIPiMu{W$Us$3~^K81(Js=cF-6#L(dI$ry%dkUa8T0V)|>TLfUyO%bGODwEL7 z00B(a&1gU)(KIk>l$i03w;5Czw@@Ti@IN8Ihk|cMo7@=j?FPu!O*RzOmi@)DpTgbA`9m+LSU;fef1J z7}hcBdj=^d(V+MZH>BI$=ypc+DZKP&T+fndAKk{zra_!!-#JzHM;La4kw$5gwPx*# zJCscs8k#t2^oINMZGp{=Vc&=Ot@szIJy#ZZ9m`Jw(m(w^5Ia<|$bUWs<~7IR45860Oi)7;Y9`46d)OuGu z!mAlO*GBIr!C;{Axw;&@xKF{l)}Qhp%N_Y&tx=Jeic@k?4xMGJFpJ+pJ86aiS#TrP7Y65#(PCtsgr977ObR>lQ z<%4x9aNfs8DKhxM&K?d6tgq|BGF`~u&6}t#MA>_ZAAd(5ba)`7M+(b|%4ztk_>{R0 zwoytQebCDk3H1hcns!4U(jK~sEbs#77^m-Ayc;uBD=T5|K1*MDODCC5jIWf`jHN4y zv%Nr~OlStf4RoL2Z%srtvF=3XcnC@Euyh<@PlNbqHIXcTuO5yTPDvfZ@}87C zHXUjO%9E{#!|mkgIN@3Bij@bIi;P~@2IOOe&PHE0^eL%iNEKw1c)>+#LIA*xA>Fs6 z&`H77lE4z|0!o1st-@u(=3p^#FM&RV>V2w324XPy!^?)JYNsJ^a_k9f z?(Q?7S=0VpYTt^Zy%*Q;3a;7Icf?4T)eD^40Cx6QkABD3C0v^uv zh=Xm7F#iA1Q1Ji%HdL8P58Gq zxET=XcVeWchN9}#jyzjf_!PtjHXJ6~XhR^<`YukxS@NADv)1mwfYoE%3y1X{zgZNo zpI^B#Chd6hgNoM01(Y1ZdS$f|rxNB3DAk2eLNN{}eC56zA)x*$gx9UIha9(9piwnl zRRxwuerj|5tSOX@4yMp9$=^sZ*GSvgw5ydd_cK%j|`MxrAZN{a^Yf z1u~R)5A}L{;r3l$+@C0U{=#U61}ze)a`OE`(Z|@nk-FmM*>rB!RVN+zQ{sI5y2M26A|q zv~-es|F8DmGpfn9efJE#_ugA5O6W)z2?&H9X$I*eAV{x*AV>lV(t|Wnh*DKRK)Q4x z2~8vN08*p{1Q8UZw`cBWuUTuCnKl1;_x#`eVb=bdl@D3>edWBa>pYL+cc>RJ@1m}Q z_`p>y-@^=eMRedueyHz4cs1K755A#irI=(z_4JAmMc%FSLu{4#y3VP*xbmk7 zcQddrPpJBgL0(1p4o8L z#=53<_2K&Xq@lwIbKHUX&w%nYQE)L!<^+GYDz_h8^iRGb1BvAdHOWgzvH!~2j^u3e zHf2MD~A z#;K>!77Axr6>o9OO}pGdoWMOXk{)E)9D>JJixA$0V6_Q$V?sY>Xq9M!%#~P?+TE%b zZ#e|t(a?R$!l6REYag`-0!8D4L(DeAfk*_*H44>{J~o~V7uOUZ07XPj19f{SkL&0U zIK4L5x1D^F0sCSHO+t9uFPSOFlzIBys7pz@^V)d7=N3cg(z7>sEPse6iRSY#%P~{X zw{W-omEsiS<1LvlTSy7dnsxepP|@p)f4~2l`%oa&mHD3;Id5)5Aj8 z!prQCy@vPTYUBbG@J^|I$kx46H)+SYS0B|*;?xjr658(`;iSDtgBGYX?*~+;4z*Z6+XG#ffz^jJZqEQkAd*^<*ABYec~t z9 z$q|TyuA``Y|GkJc3cATzA-J{voj61$_gPp&7)WL4J?nx4)yd<;Ry^iQQHExi;*yg+ zS}Kr@hq}6XzpD)xEc;5L2w)R+n}`tQo0*aRMb)id9#V?F6ZgyBRJYj*ihsp7d~ zFk3ncG;47@wd|Uy6#l{pFM1SoeHo!pxFc-7*X}v^iU$}0A1TRt|+G~ZGt%i>-X;-febQ){=gm@nT1iFRCS!BO$S2-Dpa-BUQ@EzIZWOE z^a9tcH9q7Cx!)*wy@>c%X^IrKIQGd#_&DZnMkZWb#dMzaIoYv?iu3K&!B%der5tIl zRl~Z^CVePZv-E7%^2CZ_b7nC)Y=W5cz^a%;k8nakL~cvV}?&h>61DvK1d>vLwVmGtL-1PpHRzfuNa9lH1Dz zmU3#YRc$q_Lv=}Xd8Ja#%nhj}i(#((xt{f{RW|*Ysi#^`#Pcv$pY3@fD|@7%RcUJa zM!Etfj}gU*04$u+nzL_$bMk9Xwa8XbnK_d*aUkMG<}+!Tv%-^~pmDUl_T|@~8y~U+ z8Kr=!yg;&dn9KSyeV;nh5FHsC&_Ot+g`IH>;=7l!V4{HrTSV#Bjn40%G^Mnr76P)W!BRbQ~z7>CnKmEDX|Q@ioWnW+tE z?Bnjsde#R}jz3gQ>~05bQ~qw~=E;E6eErR5Mi&Tx6ZQbq@NI(AksnArqE=E5;L6wo zGl^L@@w#c^SJjh!8dD*GI9^+I0HTF!BktrfM{Qf?;L97z3fo3H$M4& zeUig%&)7Fy8-YMvgVKPGQ+-l%5uA{M%asw0 zcqRXdBdbM$Te4S@>wffOmSE1M>op8|nVDAkCjfr9VqM&nxwNQ2dSxIx2|+sj`l$Mv z0>eJ8h*!}PHoh_=(f^^1PV#MK>;5s^Go|f@gk=R~)WJ)%*=j;1;BH|FBV;gO<;v(} zw+wDgPC2t^?Bg&wd<+cv20!iZAT;v7066^UhSUt^_Ly{=Ci<5*%32MlrrEY}d5Vrk za$Cv5zt$lNtpk2gDOzB1X~gi|zbR?Hr~?zcjXUsODjFC-5|XmlY1+*$L|OrgmiMkx z7NlXxY(|^U3Fo{Er*E5b2I5Yj8KN4Rshl`9)C0bb5&tXuu(ACvg3KPSdKB1TevgHM z5k%eS^@HY=)+VuSTwk1S-$f2i6mOC7K`1Qm_S#NDJyHkcvh_ zJs+49qn2cnfii~1d(Az5YilsEhpUwv1|#Lm1?b=bU{qJH_@csyVS3h9|!(7jk(llM+cURsphE4j?8An1Pb zJR>~|VB?61U%@T^>t4nG>oFeqWTuW+V|ma!*snpH=PID4(0~+|d(Wm-GnV@WX|&9W zP<&Z}2B^|n-XDta6G|^q7KK2RhWkI{G&i+MK_kgw*Cv#gzJo)3AS#8ONf!N=`s*@# zoiXkS7q96nBXYD*gC8#IGEhuT9WsgHW)0;uiQa<&+9if6f3#)v9?iv+Ib)RDRx8Ik zN(aDwU~O$CSz0@P3(f}d#xyKcbd~BiE_WL)A=k(?Mpg87$nhs5ZCvp9O*sX1tb6M2tM350hq&$iVwfV(_Bu@XlSRyCDWN) zXivv_s@d%~gL-D~F=QWWGpPp(0P)IvuQYYyfJW7rUi#k_e<0alScic8Ibpwjd;E1Q+D?WwV*u?^?iG!8yw7ipk~A`0v=Z%!TOv zdH_Fh;AB6lFRLNJ>m*Ki+XAiKZ#5I zw_k$}ciLJdcBtV}_<()nNV>U6`Gd|50Mq!nX!+x1c|taGW>R5Zdxk)Amc^{QIb&O1 zm6KOq!mdpC*7Uv_6!~Qb*YSJ(Ra9;ZvBIKbeJ=Qw1IguH zB(5Qc(VYs?HuKB?};Co+qS@czkZ77haCPKLf;M}E0mM8h)LpkvYzUikl z6YN*MKzjh1((;No^2rcZ1x!t;c%b1pu@G`Ec>*&Jp$~;3J6h7Ik zCcUvnzCe<&%L_)>dPDv=5N2bmPK^x+Y#7Jb9{o&@o>Cso;A~E^G}0E_BrN>{zEp`Z z`{M#FTqwwFNd(bvh7%L-N6Mg;vWc9b87em*nTdiwR;`Fp4LX2(>UwTIbH-5r4n*Be zqxHreHr?cfrfN5Tr(z34L<8<4L^Jj2r4^qcPb3pl65p)*kBvJ_a`~3kqkq~`j6KTU zJh;NN+e|Z+KAJ|wlI8a@G%ChsINIhf&HqxGAB4t zQM(QOxvTYF(HZ>*xfXfu?iDndY}s1;UpZDf`oAc75Qmj!1xqxknE)2cCy6!KQfi9j zk^|aiv{+l#-)|g~@c4mss;K?57wLy!FhvyA31F3$C&m3a2VC_rXG&Xss>;d=WW8k? zmpBn>_yYV7AjLLhyG!(k9wQI=wr$i--wX|{cCOi>R=d;gOJ&dw31;w^;*Nho?fw=1 z_Wy0={XfUFP(_y}Y&fPXntwfrQq5@j6b?jFW11EhUzdiZKzQxTFuj7EPLV-6G!(}pCO4+DAI?!c{3)bUP- z*o1VVti1+^<4pev$Bvq~!A?HsC2F%5tm@;0-?%w1&tv{iAqF1FNAK9L_0PIj(9*wy za)gU~-81$_e48yzrb*Zco0Zy6=jJ`wAyY86$htLgF7^@Cl(;Y5r)-$Feu=rH9R7R8 zp$KN}Va3GdKQIt?2o_|C{@qU@x#ZT5|M|k?Wp83NE<1Zv$_w=+Lg@5quR96uGq)0w z8Y?6uvaNxeE{cJ}-a%y<2u&ha=t6?;vF7sXp^_Ur6J=#QM5LE_q7$R2F|l)g=Mx3`Qew2a@0m+1?5Yk!c8*OPqYDbHBSNI>0b4e6;`_WpuxYFVAJ zs~{dbd&udSJi@Q^(=v|~Jnge2w%Rkd+>|yC-0+8clHCRAPnD6BMyzUgV0>L!5>)`K zrYd^~VqOcREuZx&Zh0u&k80by;O3}g%Ov!aQH}PWh?tP?%W0afu5##ueS4}B+MOaD zTKlI+B>yb%fD@-3H%DzY1rixzm{^G;c}|~0&n>-^LQkcb@7EmAq;@BfU^_cdeZAac z_7M;S9@6>Ne>wsf1`G9R$7ziiM@sz_v@l^m9k>at(!A{Qv+?s=R!15mUzcf-p?%!Y zN+~Z&MdJljl_Nw6S#jZ3dYN%i6-;chEdobL&$_Y}XyP_HZ$AdK?|LmTV^`sY;+!7_ znz#|-*a~;bj{6fv*fO11&OOrLn^n6_oWro#1L}W_K#b) zk%N&msVy^G6HgiJyk>=0hCxGg#g`LNN1AWql%ReqH&j>C_CYl+N7Jlc3&C*H3OZ8O zuPnuqOP!|ZODmn0z8t;6f_DXX!&pA%x1OzQF)zqTLc9yjAj@a{C6#LfCnqGM45`A@ zFk!rggRAhm)dhgv(_zRUH%JmJ6GU^$+M2Mu(rF^b2OISlrzAT|pHHamk?6$t!Tv0) zfO$@bfit1X!&BeU@p`mY=q0~*;2a0343l0gsCi$%%U7T8f}F6+YDpA3I6RH7;=+R* zgOz{Wl(cJIr3K+y_mx-c5@B6*ect&1>#;Hl>&M@T)rS0|*q606!{Ps*D(k;kp~t)< zGhTKrBg3kK3=kaazA{KuxBB$4Z`V}jSxz&#axt?@2{<7R-nt~6ZU|@+uV)XP%f3wW zojNM%l7lQLdPo*(pQ9Y*g12dBGVbn8h4@}gIuMNsooyWzh2sOcEMD9MeVY>G0$5En z=SHC-hwqwjzH@Z!j2S7SPk2kDB|auM&gKvSmyRk=%Zf!}SJy1b%H~pO682?ibY*=W zKUIVyi+}NgLw6IKn4)7ix#?06#~(zULke^G@9}Tn+~*ClB;%An$x6NrpLJLqWXUMx z@`CpCV}i3rvgDML2NxwCBTj`cZL}S2010u=`SIC13PiNJ>|7uYxX2}<+e0nzZoe^E z{7OEWJu`v+5xDuRR0w2X`0*4oGW4ye(bm*qp`~_^S=s77r1~GUA(JrLmp48@o z%N~i>RyPw*f+BJA84zvdk71Qhh&4+NAmrTmdB2l6mgZM5Fi1f-OA6RZrg1&;whQU? z864s+L78Z^#}% zn^BTyU9AQI*Cu9im=G6f$=B^NY?LW&uH81DIBQNXPe$O$k;h08G(2(ff*97q{GN4{$xZ`r!wynPRw|?7QHkFl-EB zx_+Idw(9`5vi7I(6Q2M*%^tk++q^nx|CnSV;D-U*>fN+0Pa@TC)(%Pj12VPB%PsOr z1?g1jmRx2TYt?@ufb`(+XHI)bHF{bzey!JK8Xlg|l`t1Pv(V_t-`;ppHXORG^ca6= zJ{tdRGXMh|xa-w{Ztgw6T;<-D5Qo~`4Lj(J2pkb27{ZbvTIk?6^Dko_tge(3( zH+28II;n9u+m!Q@JzorvzusovVD}HB{x(YAR{y24gXFwaPkca}+&21o-we5>sks>& z0X#YC^1nd@ho`pgtPa3r3&`8nzsu_%qyx7xToRJ(Eu434UG5c1n~iJ(K#s!ckNee* z2X@UsT~lYWe;Lf6KhPq=Znqe!UwyBay?`C!r*5UCT$~PkwMUDg#YUIMrQ24jAXAp- z(gPS!A*^LzmNq678c>77sk9DD!`KfPcKh6&=H#s3xXO>{oB4X3k%%ylNS2%+O^Y8w zlZ)#@7NiI>^5YugTgz8b>2vD{5ryt1fuS`)rL)2>>4Qud(HC!Dd^;)L*f}C0uKymR zA6k=v1mNdrtE`|p#V2ss&P#~P+lhhX^vO)0?*pK!r?rRrTQoGpT^r$EGjS}3Pr7u$ z%;W*~DKO+_3Ksib(VK6!^Cbx@k-C&?kG=YHvgPF|$#He9Xhns8RHfu*^ia@cf-~)c z9rPX0dSVe^63|}^zR%Ku>7qWnCh@Qq5@wKFGmP|9(clGVh0P3zz4)Pl%aTDUFe3YF zUICkhG#O&hQWs=)eC{hR9sO6^h)}3}NMPWe;0E-y9?g*Bjh|ib11nOg695+^z67Cs zYG){j;5HV1e2+cAyqKzO5@W6TkoD-8gVjlZ*tJ|?P9Y|1oXtrun0;>(nzUn>tAn=; zqMNN-F=t_~>e4lO=6A?qoT}f7>;B!&-aB^Egv^lQ^|(U)q5#dMG3H% zSS3Hq=jQ!RG*`*gN-<>_dzLu7Hr3v|55yNbejFaQwW&uV9^94k2!xVrb9IHk)7o1| zqY-x?fGDO4k8x9!g3W1q-T&NO`oX<|&U57^A$rI*=C98$8*Zok0P06`BArpJ-yhuf zaPQ&W7+PBnDce|7rs8^(f`1|~QZ`&R>C0Oszot;|X~BVL5@pBHP=t8ubqeaZ6vbiP zl5ZVbZ_U{Pi;DgRX%c5KNmU zsqU(ZCrZUVR4s8SOXuO8A&cFjkN*1L)AXWGrf$j7=O6=$C>=ilC`X1h9!h!&KeFQ8 zteg#mKK8It;cQS-bDg*FHLeW{zF)0zJEn)`^d{*0ap!u2IF*qE(_K(259LpM|Je;Q zbuotX(~Hv>G00cZYX^k^kV}e^#}VAF8sL4~s69%`v&dbvT2RprT6R(?LhXH+o8kRZ>E)zb%hKbnXETQ~#Ae z4Y9=R250wYs;slg{<*&;r)F`u{E@*C`LG+c_<}aN&EL3h4LO(J5Z_Sv>&;}p`P|%6 zfcsi1-1b&HBY>1|`~DW;i)Yn1W|Vou8(zOKrvR~L&FFfxGa<i;HTD7kFRGG@v zlu%3SrA-YXes8PnS9(9|iHv{01(nn*Ub(=?hdd?p=)CL z%$O!UM8M1CbNLO+96GQnC!-TgHq7nA8pY8=Cr$=wV2FHUIQGG3m?7e8P~=o7R1mhy zoc|Z?#{hMi4{oJ+jHP>ZvY2|Yfl`#XDz8*U$L0%e&ZWVCw97y2cb7rk<;}G{OB+xP z{_M8Li#nG==;wa5AAds=#HjQ=Wx@v|lkJKraJDUcynyDLdCuC>fci3H@vWtYNnscE zf~uWCb~HVC%@BB~R7v1B*9qk=c%;k7&6jd6AXg(bIF7SR-`-QzwxE_Q* zz$*=+DsnTGaxsHQE1k0EWOed|`T-WC+!(&0iPH8aQnC zRhQKA?AJeEfTosqk4Qmjc$DQPw_IQOsZnB>L3{Jz{y64N^v^ioue%^cMTOyB(GI4C zd-R{l?pw>RSuoSSAn}DA+`>@F6^<7ab<}A%$*C`=)oSTha#2yL{O6;rXI2mRXwi4b z#?0|#X;*u6bp7{On)(I+zibWC%mAZL&|`Brb-x@`RXql1sv=l(QS z5%3h4og}@kLD|_d5L9xi8-Vb(SgVFVWbbEn$4c`;-n%G`qbpQoN}Q2zW#Eb*9r;hT zZ%xghxd>Qn!u4dqQ6moa)}yF)(I&p=c!kDmsxo$X{I7D4dx@S$kw zW8|nrR?D~T8Xf2FP$yc5iAK@aXR^nML2p9t{fdR7+M}&;gNL*Se(&98OTR81O#Jm-pCm|P-p)1i)GR6~$l7@I7wX9$cU zu(F9$H~J`4Q3t^@ez>;!K+qkU;7s!7)mPNBDI$X@!M3|6iN< zfe^h`Om~1)${uSs{ghj<;fSAvGZwKtd}RECiIFY&xKwxTTF9D4!qd@QwM$KG5}!?9 zRyS53$x)&^{uA$)|J9aZGq_7_!!V|#sCs2ig5sdL@2cqzuAzT4BaG~e%9tBiuiM0H zOWhaL=E!_1bm~mLNAiB2njT5`o}R4uDirMbvE1FdE3gVbArxntdy``c)v&EYLG{av zjk9WvrtbvqPS8ua9wt+scU30>z#>^ww;d7(hLCuFdKpbgwaO%_W?&_wM9#Dp@mc8& z_;qRd!3V61;qB{6vC5(axTa@)w^^@t)-=?&)zi6J17S5v!@+=nS?d9NVJyy|5(IQB)$>j}*iLJkLbFLS&%@jT`3;c>} z*^W>7-|@T*Npv86Q_UY=6a&^Tco25_XVhs(q`>Hv)C<~4l8CQn^v^b%?1D}KoNrnf zv*ITt!GZK3Qv6(@i*`X~8hfxC`UDcTIZ!Wc@+^7EitQHTdbqQI48qmzQedL0 z0k;F4h~{-Y8;O~Ruw|-d`BY1vldgw{ZM0|;#e~q)>m3g-J14FXDb=Zk+|Xu3`s+C` zut5w>4#HP`c|NdunsiGx2eG1pUws>^(iYS~HE|CPOZ&u;G5wKdxy^UY$_WNy2mCB1 z*9wzAG?HDx%WIOY&KXxo4+8GN18ih78_KiITiND~4Y^aHt=%Vc*=!Zb)si-=&mZ^~ z@%!Q;JfIpPQMBmR{aw`E^cts{yL5&u9|wdoeAPaLiv>PsE@o#P03|%nY~qVSy9>it zUsn6aMqItp-o6P(*cR}Et(z2&N%(jw&Jp{D)lAk}w|_@&Eli>^vx;Wk>iD~UPs zl1#ISd^#BkdovHHrL7)m+vlz`Tw`P=h6himd-ZY<;1v5(Hh6TLA9E+=g(0~2v1{tRPGu6)-=Lc|7r-q+gBni6xl0;%m1`nu)b-~-o|0Ua zhB8%9LrEM1SJy%);E^3KMCb1TX^yCJvEZ;sjmv_AM5!5dS7RC>a*S|{cdD=vlajVQ zi-KqO6OMP4V3VV9E$`N7?9Cj>x#)~mK4jiBV(60TCr%4zHcAoZjwz({~!i^T*9a zh#_SO!&9ffMb?~}-I6+~))zW0J)GK3m>+)^^Xz+oSBwm|dqH{!R)L?Clh9tbAjlf_ zZ>cPR^NZ!N!y~%-dOc_4#Pn?J-yq~2h8%A**2}7Bt@+?{h_=g|(1OtmVc&o+p41BHs(7w0PH@kf0AF@{NZ|fvGZoYDMbQe^ifOL8<0X#U zFz-b(%9A|7A9B(b0f}^b;59)8#8&`J^;#@*v6!Qx zj~Dk`#%xG@Jzdr4s!l_8I+=-E>P zD>U2EnVk4?^d8zV{E3r~w={bLXww@$vrqLM`ehk;IlC@1-FPS)6rhhIxi1$k;pJyo z*u|B2cs08EG|%LewVhP82R{(_|2((EX3jkvVBxOUiNw9lYb@*-%N8UU@wbQRoN3^4 zctztT^R;4c$h%g04zLx0OPYil%dUIpJW}qhNt(YoHBy+JbcfU?}Muy;=NDqD7bG@G$L8_xnBEJLX$+)3NbWU5TLSdnXBz)YAzvzQdyl z*5pHerYnzqP0o$8s(wp&{nWLPVFDA&+C1{!+u}zV{C%O~E`CQd=pem{&bWAU->;!$ z*<5oi9R$;xSAW48jxzuP4o2sLE|K)-12Mxi>|*^WZP#Qf_QW45MJY2z3`mcASU?ap z7rY)kl5=Yyzd>WeUo5%fQQ0h513Rs)a-U-~lSXU(}`dC%{r;QeI;`MYZ(@g)AtlcJ5x!A1V z<9-JyzfH=ub`ld8UBuM4T=+I3)DCFG-W4p(0!-Oq}5H)sUdV%!0JVnYul75Y&wRh}_%JNk{wZzE3(rn*rZfd48<$IhD zD_ldG^QuJsJbkHie}3dblbc6CE61lEVUK*h&R81at&6^Q<||83L%x>R3GtyhW;Y_^s5p4Qw_8CSbjZ+u&1!c zw)4?M7whB6Ow;$=Fna2PiakF#-&Gv*q`Pci1NkZz$P%t^%0N_&A7XY#(}C^kgvlSO z$)|q_rJa?+tn*fbqHExu&{HNciPieb#}IFz1x*8_C`;KgT)fFgdR&n~o3M&)vfV>C z%eL@Jt7gJrzNG8g+Fog<9a<$k4Vp#e%XJoJbNjNU zks>yr#szD-0^-rTIW-;+O9rRYZVeMs#U3_s7ZrVOs*;tJ*xeOc7{EH){jmDS+437o z?tJo)UZn&nzJ2-f#t$>F+a&JQ`QT|5kVms+^x^PY0Y((%{EUC0OQjq0l}|>86xaIc zZ_uth#7L2E%SO2VO{UZ}b@`#{=E*B|HLuW8& z`J<{0*~2Yv8R(7CxsQN%Pisbe_Umz<)ABz-=BI9=qpst9`xJMn2Fj8T=Hh_fT);T9 zuc3u%zd{+d6FKcv`%-9Ia6&{WYnbrFGz-n>U1R=Lj+-caYqifHqOI$z@xzB0VKEMJ z+`AD>ajF=N^zv?7c`fmWr1W!s79%MU<2~GPurP^!`EJf?vSCd+Ks|;H#9oQ zU4uU(fY}Iry1SyLla$Bspr@h2Yb=9!GMUZFS2{jO*NA(V=R03gsfRovM5zw&Ze+qp z*LT8PaP-+j;X;~^3#Vi`?=-67h$IE{aJM@A6gHws`vPhf# z12PlGfRNjy1~)GQSRh(By@7yrY27H7R5m+6GkinSVbg|JOz8(XK8_mjkB-{S1(`Od z2%W$!j3W|BDa$z%A*mA&cpbiJ2*s;&-~yU_%n0;(P{-z?6rJrWtsl{cV&c~ghliy+ zJwwdk_cp3=MVh5!ncCu+UiGjyLa$jEr4Ol$4*e5qY3xwTA4iymk@h;EPMg|2-D0@$ zlEA2$WepNfwx=Mf>10P~PG{xOUC+t_Q!KfpmGOAX4=KfBh$0apz7k|_ZyA)6NTxDg zfwN860WrNp&E$p&Nms*4k(8-1WE6#JC)-${acp_iJ89~0 zT1L-76B+BPDDg0lj$-Ux+!s+pWfe#uRsMm}x3$v-*FJTw&@itL=?!isS6ya{c&Bh0 zxMmw&HE*eTl``nhr`l}#aS0U$^*YX>`_svB0GKCJxUR1BO$=Q_1>|RK_1wnBxjK)4 z{@o$VcluThlZINaK`be{?51_Vb>-9Qv5PS5dUyDhkTXvY7u_1U1y*a5?tI+x+0^Ok zsp&x0my3noTw&*-GDcW{$%Kp976hP4IJokP-7QH#+}k%EGX=sH~Heo~u>g!ZFDk{L;`l z#rCelwAhVUlGP(3*_;v8`XisPTX`7P@__cVWd@Ha-*IpIy)dYhGU`5dV@!?g<)*FF zdaY%~HRctSKPe(4Mv3M5iXGRba+j~%7xWdZsilf5k0vi z>;ZP-#|k)I0WswLoTH~sK*mlci;~&ipmIU}4Feim7Qu_=CUhv@R2X>1% zm%SE8bUubkanuE11#Zg=CfiAgwZH8Kphs&r(umwel`b$$>4f2AZnj&saa%Ls+OgDk zXX2uWyCWf~+^LF`aGelq+NE7azc)h(rnbhy=i0tX6tsXg)RPVyZ$*3r>}O_ZbY!J^wDmbUeXWSa5qro6aZFBV4q z>Uah)Y6$NX_ptkZa0wT5pW4AaPbt#A`B*Q;$pt}8XQ0u>dtuL4AMGmuKQ?0v5S26f z-6nWz#s$!^yT<8zeWKOZA=4j0Hf8Tz5of6lflZBLu84ZeAn-6Ygjru`ia5gv3!W-{YST_EKIYuxWre9U}e!hd`K)$_- z2i0Ej&=zip)aov-5lTGS8CtGEq1;={k{}h zn8lK)kLt@<%X_FQqQ7Vp`mu}t7AxE6-=OzBooDYkM9rg*VDcY0Aam9WMG|+Z@4aDU zm6umj((xG@E3tg`@U)_6#`Kzomlf^Pf8$~Lf83p!NWqUT`$DAr5xcH^bc;}0^mnd9 zc@u--bmD_tVnU%(UAh)P-Rsx^_-COF9{ipU@XSt9atN2rE+CoMkcOr;?GMMN{I6}h zR-7->QdWY#_6$6lTv*b;ZE%!5zXhh+FA%rl9)fu6wAsEo${F4h@Kk@p{N~9@jzp08 zi=%9Y3HOU80Rs8D09zWHgqGV1mZgn$ndNI>yOfnLr-c+gP2J1b-z0I{rXu6lnXg9U z91gogt`}(_VtxeHm9*gIg^+o2zdjy-ikUbfw)Qgh3q)13qNVx!P1vn-u8k+Y+DGmm{7l{V=E(b2X;ExVq8K{2-T-az3*&IqN-K zVd5J`Yp1X?j+m253%$?NWhCS_!L`7vKc38dru3rz%Z*sq+FDvky3C)Z?ABx^rjvMe z-ojlIZWxd2ONpY=oP)#${ikq5o$15HDZIQ?Y51Q@B9E*!uHGa0Jr(wT5`xue9(EFF zIT8h*8`DkD&C(+(z&1I7qRctD8KX zl)Qvhj~Yyi%Kb_8Oz}IQ`5eKKw!HJbG&j5 z%PI=p0hbFrf+GRg0$aRCMCM!y8|FeK`Ws)Zf5Wd6%e!Pmh z=zs(8Q)WWR`CCZc*xHUgyK~V{26XjYgC*fPbz5BN7Pa2grzHVeTnozFprseB10c&V z9_M|hE|e=H(Yr}JzO$;dvMX<%GNaB{PVGcq#OT$@2A_*> z`jnvbbh*q-kU1dBy1nZeW&l%?mJ`&VV9AYmIR zg(kXY&dPbEtN&!r(@C8l?0i;s5u-h3k8~o#Y(DF!|M8XH9!9sR`UPsDfRz;s{dke_kSr<|9c_* L|9c(&{q_F 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

    0;G?5tocoJ2aCaLN#5IFj22y%<#o*SV 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 literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/item-hilite.png b/lib/layout/list/samples/assets/item-hilite.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9c07d40c6acf1f4936f556f48125d81a7d579b GIT binary patch literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^4nQ2n!3HGjpG}AWQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtZVz*NBqf{Irtt#G+J&fW*wa5h zJyShH1A{L`3xUS=c)B=-RK&f#eBJS|gMjPBmCn;rJ$Vy_ea@LBXf(+9`l&5XYu{da z=cfhhp52?n-v6i%xI`)X~z zdN;#Vy@oTZ&guhMPp`5hu zo7GoY3nF)}`p`9O^E83Z z&G4CPHFM(eSHukG$2)R4xZG#!crM zCreh=+>!&b_U&Vso|@as-pvqM?Js^{Dffdu|J%wAX3Mx4j6eO@63bXt${6$i@*Bfr U>GAKD0b`HB)78&qol`;+02l7vssI20 literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/pulldown.png b/lib/layout/list/samples/assets/pulldown.png new file mode 100644 index 0000000000000000000000000000000000000000..1a452097fcbea95ae9b59949149c81b7a107dfdd GIT binary patch literal 3031 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 literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/search-input-search.png b/lib/layout/list/samples/assets/search-input-search.png new file mode 100644 index 0000000000000000000000000000000000000000..36bf1b5161e9d6b22273b681e43c85859c7c8914 GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/spinner.gif b/lib/layout/list/samples/assets/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..b412a684db625390e8dbbe8be69262dbf3b19ddd GIT binary patch literal 664 zcmZ?wbhEHbeMM79-hgQC)?WEPMtb+{rdG)RaH-(JUMsn+|#E|jg5^N z7#L>GoSBxEcIM2P|Ns9h{^#~{4GDI33~)8lGhk)}N-O?kVdVmvrUPUHDSie97N-v< zGpEh8XczsY!u2sE{E^Cy1w4|E6lN^oxcN{fu20l=q5U$Khm)QnGb{K^KWY1ZGy>f3j8qEXrAYw_(GDG+gX1D$CnAG+*uHwVgs7P2@Wd*gPmVi zx$;F;->GC^&Jj(Xw4h^M^hJ>j<;8ku@>-l0G#iDqwLVk~;LvJxWe}B_q=YbpiGc~> z7|qGvCiYJzENd^WN%_gZlVG%_bJemG9k(!(RuLV?Yk!PxH7`)G$=i9x!O(zHgvl4l zF$@fBK&OBL#^8d^=T%!zF5PhGZ%4Dom2}y2iR;7{3dkQ|xW0f#esO%0l1;1IL&e2w zr97^wTKsWA3K<5tV@y8SZtmIhqgAwM*);X87N?#|3wT~AYdC2qy9TFpPWJGfugKT3 Wq>R~sp}+a@gG7sHw *:first-child { + padding-top: 4px; + border-radius: 12px 12px 0 0; + border-top: 1px solid #333; +} + +.enyo-alpha-jumper > *:last-child { + padding-bottom: 4px; + border-radius: 0 0 12px 12px; + border-bottom: 1px solid #333; +} + +.enyo-alpha-jumper > * { + background: #eee; + padding: 1px 4px; + border-right: 1px solid #333; + border-left: 1px solid #333; +} + +.enyo-alpha-jumper > .active { + background: #333; + color: white; +} \ No newline at end of file diff --git a/lib/layout/list/source/AlphaJumper.js b/lib/layout/list/source/AlphaJumper.js new file mode 100644 index 0000000..13cf843 --- /dev/null +++ b/lib/layout/list/source/AlphaJumper.js @@ -0,0 +1,70 @@ +enyo.kind({ + name: "enyo.AlphaJumper", + classes: "enyo-alpha-jumper enyo-border-box", + published: { + marker: null + }, + events: { + onAlphaJump: "" + }, + handlers: { + ondown: "down", + onmove: "move", + onup: "up" + }, + initComponents: function() { + for (var s="A".charCodeAt(0), i=s; ienyo.List that allows + content to be displayed around its rows. + + {kind: "enyo.AroundList", onSetupItem: "setupItem", + aboveComponents: [ + {content: "Content above the list"} + ], + components: [ + {content: "List item"} + ] + } +*/ +enyo.kind({ + name: "enyo.AroundList", + kind: "enyo.List", + //* @protected + listTools: [ + {name: "port", classes: "enyo-list-port enyo-border-box", components: [ + {name: "aboveClient"}, + {name: "generator", kind: "FlyweightRepeater", canGenerate: false, components: [ + {tag: null, name: "client"} + ]}, + {name: "holdingarea", allowHtml: true, classes: "enyo-list-holdingarea"}, + {name: "page0", allowHtml: true, classes: "enyo-list-page"}, + {name: "page1", allowHtml: true, classes: "enyo-list-page"}, + {name: "belowClient"}, + {name: "placeholder"}, + {name: "swipeableComponents", style: "position:absolute; display:block; top:-1000px; left:0px;"} + ]} + ], + //* @public + //* Block of components to be rendered above the list + aboveComponents: null, + //* @protected + initComponents: function() { + this.inherited(arguments); + if (this.aboveComponents) { + this.$.aboveClient.createComponents(this.aboveComponents, {owner: this.owner}); + } + if (this.belowComponents) { + this.$.belowClient.createComponents(this.belowComponents, {owner: this.owner}); + } + }, + updateMetrics: function() { + this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100); + this.pageCount = Math.ceil(this.count / this.rowsPerPage); + this.aboveHeight = this.$.aboveClient.getBounds().height; + this.belowHeight = this.$.belowClient.getBounds().height; + this.portSize = this.aboveHeight + this.belowHeight; + for (var i=0; i < this.pageCount; i++) { + this.portSize += this.getPageHeight(i); + } + this.adjustPortSize(); + }, + positionPage: function(inPage, inTarget) { + inTarget.pageNo = inPage; + var y = this.pageToPosition(inPage); + var o = this.bottomUp ? this.belowHeight : this.aboveHeight; + y += o; + inTarget.applyStyle(this.pageBound, y + "px"); + }, + scrollToContentStart: function() { + var y = this.bottomUp ? this.belowHeight : this.aboveHeight; + this.setScrollPosition(y); + } +}); \ No newline at end of file diff --git a/lib/layout/list/source/FlyweightRepeater.js b/lib/layout/list/source/FlyweightRepeater.js new file mode 100644 index 0000000..b6cd9ce --- /dev/null +++ b/lib/layout/list/source/FlyweightRepeater.js @@ -0,0 +1,248 @@ +/** + _enyo.FlyweightRepeater_ is a control that displays a repeating list of + rows, suitable for displaying medium-sized lists (up to ~100 items). A + flyweight strategy is employed to render one set of row controls, as needed, + for as many rows as are contained in the repeater. + + The FlyweightRepeater's _components_ block contains the controls to be used + for a single row. This set of controls will be rendered for each row. You + may customize row rendering by handling the _onSetupItem_ event. + + The controls inside a FlyweightRepeater are non-interactive. This means that + calling methods that would normally cause rendering to occur (e.g., + _setContent_) will not do so. However, you can force a row to render by + calling _renderRow(inRow)_. + + In addition, you can force a row to be temporarily interactive by calling + _prepareRow(inRow)_. Call the _lockRow_ method when the interaction is + complete. + + For more information, see the documentation on + [Lists](https://github.com/enyojs/enyo/wiki/Lists) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.FlyweightRepeater", + published: { + //* Number of rows to render + count: 0, + /** + If true, the selection mechanism is disabled. Tap events are still + sent, but items won't be automatically re-rendered when tapped. + */ + noSelect: false, + //* If true, multiple selections are allowed + multiSelect: false, + //* If true, the selected item will toggle + toggleSelected: false, + /** + Used to specify CSS classes for the repeater's wrapper component + (client). Input is identical to enyo.Control.setClasses() + */ + clientClasses: '', + /** + Used to specify custom styling for the repeater's wrapper component + (client). Input is identical to enyo.Control.setStyle() + */ + clientStyle: '', + /** + Offset applied to row number during generation. Used to allow a + items to use a natural index instead of being forced to be + 0-based. Must be positive, as row -1 is used for undefined rows + in the event system. + */ + rowOffset: 0 + }, + events: { + /** + Fires once per row at render time. + + _inEvent.index_ contains the current row index. + + _inEvent.selected_ is a boolean indicating whether the current row + is selected. + */ + onSetupItem: "", + //* Fires after an individual row has been rendered from a call to _renderRow()_. + onRenderRow: "" + }, + //* design-time attribute, indicates if row indices run + //* from [0.._count_-1] (false) or [_count_-1..0] (true) + bottomUp: false, + //* @protected + components: [ + {kind: "Selection", onSelect: "selectDeselect", onDeselect: "selectDeselect"}, + {name: "client"} + ], + create: function() { + this.inherited(arguments); + this.noSelectChanged(); + this.multiSelectChanged(); + this.clientClassesChanged(); + this.clientStyleChanged(); + }, + noSelectChanged: function() { + if (this.noSelect) { + this.$.selection.clear(); + } + }, + multiSelectChanged: function() { + this.$.selection.setMulti(this.multiSelect); + }, + clientClassesChanged: function() { + this.$.client.setClasses(this.clientClasses); + }, + clientStyleChanged: function() { + this.$.client.setStyle(this.clientStyle); + }, + setupItem: function(inIndex) { + this.doSetupItem({index: inIndex, selected: this.isSelected(inIndex)}); + }, + //* Renders the list. + generateChildHtml: function() { + var h = ""; + this.index = null; + // note: can supply a rowOffset + // and indicate if rows should be rendered top down or bottomUp + for (var i=0, r=0; i= this.count + this.rowOffset) { + return; + } + //this.index = null; + // always call the setupItem callback, as we may rely on the post-render state + this.setupItem(inIndex); + var node = this.fetchRowNode(inIndex); + if (node) { + enyo.dom.setInnerHtml(node, this.$.client.generateChildHtml()); + this.$.client.teardownChildren(); + this.doRenderRow({rowIndex: inIndex}); + } + }, + //* Fetches the DOM node for the given row index. + fetchRowNode: function(inIndex) { + if (this.hasNode()) { + return this.node.querySelector('[data-enyo-index="' + inIndex + '"]'); + } + }, + //* Fetches the row number corresponding with the target of a given event. + rowForEvent: function(inEvent) { + if (!this.hasNode()) { + return -1; + } + var n = inEvent.target; + while (n && n !== this.node) { + var i = n.getAttribute && n.getAttribute("data-enyo-index"); + if (i !== null) { + return Number(i); + } + n = n.parentNode; + } + return -1; + }, + //* Prepares the row specified by _inIndex_ such that changes made to the + //* controls inside the repeater will be rendered for the given row. + prepareRow: function(inIndex) { + // do nothing if index is out-of-range + if (inIndex < 0 || inIndex >= this.count) { + return; + } + // update row internals to match model + this.setupItem(inIndex); + var n = this.fetchRowNode(inIndex); + enyo.FlyweightRepeater.claimNode(this.$.client, n); + }, + //* Prevents rendering of changes made to controls inside the repeater. + lockRow: function() { + this.$.client.teardownChildren(); + }, + //* Prepares the row specified by _inIndex_ such that changes made to the + //* controls in the row will be rendered in the given row; then performs the + //* function _inFunc_, and, finally, locks the row. + performOnRow: function(inIndex, inFunc, inContext) { + // do nothing if index is out-of-range + if (inIndex < 0 || inIndex >= this.count) { + return; + } + if (inFunc) { + this.prepareRow(inIndex); + enyo.call(inContext || null, inFunc); + this.lockRow(); + } + }, + statics: { + //* Associates a flyweight rendered control (_inControl_) with a + //* rendering context specified by _inNode_. + claimNode: function(inControl, inNode) { + var n; + if (inNode) { + if (inNode.id !== inControl.id) { + n = inNode.querySelector("#" + inControl.id); + } + else { + // inNode is already the right node, so just use it + n = inNode; + } + } + // FIXME: consider controls generated if we found a node or tag: null, the later so can teardown render + inControl.generated = Boolean(n || !inControl.tag); + inControl.node = n; + if (inControl.node) { + inControl.rendered(); + } else { + //enyo.log("Failed to find node for", inControl.id, inControl.generated); + } + // update control's class cache based on the node contents + for (var i=0, c$=inControl.children, c; (c=c$[i]); i++) { + this.claimNode(c, inNode); + } + } + } +}); \ No newline at end of file diff --git a/lib/layout/list/source/List.css b/lib/layout/list/source/List.css new file mode 100644 index 0000000..c3baf0d --- /dev/null +++ b/lib/layout/list/source/List.css @@ -0,0 +1,49 @@ +.enyo-list { + position: relative; +} + +.enyo-list-port { + overflow: hidden; + position: relative; + height: 1000000px; +} + +.enyo-list-page, .enyo-list-holdingarea { + position: absolute; + left: 0; + right: 0; +} + +.enyo-list-holdingarea { + top: -10000px; +} + +.enyo-pinned-list-placeholder { + border: 1px solid red; + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-pinned-list-placeholder button { + width: 100px; height: 100%; + position: absolute; + top: 0; right: 0; +} + +.enyo-list-reorder-container { + position: absolute; + top: 0; left: 0; + z-index: 1000; + background: transparent; + overflow: hidden; +} + +.enyo-animatedTopAndLeft { + -webkit-transition: top 0.1s linear, left 0.1s linear; + -moz-transition: top 0.1s linear, left 0.1s linear; + -o-transition: top 0.1s linear, left 0.1s linear; + transition: top 0.1s linear, left 0.1s linear; +} \ No newline at end of file diff --git a/lib/layout/list/source/List.js b/lib/layout/list/source/List.js new file mode 100644 index 0000000..70d714d --- /dev/null +++ b/lib/layout/list/source/List.js @@ -0,0 +1,1502 @@ +/** + _enyo.List_ is a control that displays a scrolling list of rows, suitable + for displaying very large lists. It is optimized such that only a small + portion of the list is rendered at a given time. A flyweight pattern is + employed, in which controls placed inside the list are created once, but + rendered for each list item. For this reason, it's best to use only simple + controls in a List, such as enyo.Control and + enyo.Image. + + A List's _components_ block contains the controls to be used for a single + row. This set of controls will be rendered for each row. You may customize + row rendering by handling the _onSetupItem_ event. + + Events fired from within list rows contain the _index_ property, which may + be used to identify the row from which the event originated. + + Beginning with Enyo 2.2, lists have built-in support for swipeable and + reorderable list items. Individual list items are swipeable by default; to + enable reorderability, set the _reorderable_ property to true. + + For more information, see the documentation on + [Lists](https://github.com/enyojs/enyo/wiki/Lists) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.List", + kind: "Scroller", + classes: "enyo-list", + published: { + /** + The number of rows contained in the list. Note that as the amount of + list data changes, _setRows_ can be called to adjust the number of + rows. To re-render the list at the current position when the count + has changed, call the _refresh_ method. If the whole data model of + the list has changed and you want to redisplay from the top, call + the _reset_ method instead. + */ + count: 0, + /** + The number of rows to be shown on a given list page segment. + There is generally no need to adjust this value. + */ + rowsPerPage: 50, + /** + If true, renders the list such that row 0 is at the bottom of the + viewport and the beginning position of the list is scrolled to the + bottom + */ + bottomUp: false, + /** + If true, the selection mechanism is disabled. Tap events are still + sent, but items won't be automatically re-rendered when tapped. + */ + noSelect: false, + //* If true, multiple selections are allowed + multiSelect: false, + //* If true, the selected item will toggle + toggleSelected: false, + //* If true, the list will assume all rows have the same height for optimization + fixedHeight: false, + //* If true, the list will allow the user to reorder list items + reorderable: false, + //* If true and _reorderable_ is true, reorderable item will be centered on finger + //* when created. When false, it will be created over old item and will then track finger. + centerReorderContainer: true, + //* Array containing components shown as the placeholder when reordering list items. + reorderComponents: [], + //* Array containing components for the pinned version of a row. If not provided, reordering + //* will not support pinned mode. + pinnedReorderComponents: [], + //* Array containing any swipeable components that will be used + swipeableComponents: [], + //* If true, swipe functionality is enabled + enableSwipe: false, + //* If true, tells list to persist the current swipeable item + persistSwipeableItem: false + }, + events: { + /** + Fires once per row at render time. + _inEvent.index_ contains the current row index. + */ + onSetupItem: "", + //* Reorder events + onSetupReorderComponents: "", + onSetupPinnedReorderComponents: "", + onReorder: "", + //* Swipe events + onSetupSwipeItem: "", + onSwipeDrag: "", + onSwipe: "", + onSwipeComplete: "" + }, + handlers: { + onAnimateFinish: "animateFinish", + onRenderRow: "rowRendered", + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish", + onup: "up", + onholdpulse: "holdpulse" + }, + //* @protected + rowHeight: 0, + listTools: [ + {name: "port", classes: "enyo-list-port enyo-border-box", components: [ + {name: "generator", kind: "FlyweightRepeater", canGenerate: false, components: [ + {tag: null, name: "client"} + ]}, + {name: "holdingarea", allowHtml: true, classes: "enyo-list-holdingarea"}, + {name: "page0", allowHtml: true, classes: "enyo-list-page"}, + {name: "page1", allowHtml: true, classes: "enyo-list-page"}, + {name: "placeholder"}, + {name: "swipeableComponents", style: "position:absolute; display:block; top:-1000px; left:0;"} + ]} + ], + + //* Reorder vars + // how long, in ms, to wait for to active reordering + reorderHoldTimeMS: 600, + // index of the row that we're moving + draggingRowIndex: -1, + // node of the dragged row, used to keep touch events alive + draggingRowNode: null, + // index of the row before which we'll show the placeholder item. If the placeholder + // is at the end of the list, this will be one larger than the row count. + placeholderRowIndex: -1, + // determines scroll height at top/bottom of list where dragging will cause scroll + dragToScrollThreshold: 0.1, + // used to determine direction of scrolling during reordering + prevScrollTop: 0, + // how many MS between scroll events when autoscrolling + autoScrollTimeoutMS: 20, + // holds timeout ID for autoscroll + autoScrollTimeout: null, + // keep last event Y coordinate to update placeholder position during autoscroll + autoscrollPageY: 0, + // set to true to indicate that we're in pinned reordering mode + pinnedReorderMode: false, + // y-coordinate of the original location of the pinned row + initialPinPosition: -1, + // set to true after drag-and-drop has moved the reordering item at least one space + // used to activate pin mode if item is dropped immediately + itemMoved: false, + // this tracks the page where the being-dragged item is so we can detect + // when we switch pages and need to adjust rendering + currentPageNumber: -1, + // timeout for completing reorder operation + completeReorderTimeout: null, + + //* Swipeable vars + // Index of swiped item + swipeIndex: null, + // Direction of swipe + swipeDirection: null, + // True if a persistent item is currently persisting + persistentItemVisible: false, + // Side from which the persisting item came + persistentItemOrigin: null, + // True if swipe was completed + swipeComplete: false, + // Timeout used to wait before completing swipe action + completeSwipeTimeout: null, + // Time in MS to wait before completing swipe action + completeSwipeDelayMS: 500, + // Time in MS for normal swipe animation + normalSwipeSpeedMS: 200, + // Time in seconds for fast swipe animation + fastSwipeSpeedMS: 100, + // Percentage of a swipe needed to force completion of the swipe + percentageDraggedThreshold: 0.2, + + importProps: function(inProps) { + // force touch on desktop when we have reorderable items to work around + // problems with native scroller + if (inProps && inProps.reorderable) { + this.touch = true; + } + this.inherited(arguments); + }, + create: function() { + this.pageHeights = []; + this.inherited(arguments); + this.getStrategy().translateOptimized = true; + this.bottomUpChanged(); + this.noSelectChanged(); + this.multiSelectChanged(); + this.toggleSelectedChanged(); + // setup generator to default to "full-list" values + this.$.generator.setRowOffset(0); + this.$.generator.setCount(this.count); + }, + initComponents: function() { + this.createReorderTools(); + this.inherited(arguments); + this.createSwipeableComponents(); + }, + createReorderTools: function() { + this.createComponent({ + name: "reorderContainer", classes: "enyo-list-reorder-container", + ondown: "sendToStrategy", ondrag: "sendToStrategy", + ondragstart: "sendToStrategy", ondragfinish: "sendToStrategy", + onflick: "sendToStrategy"}); + }, + createStrategy: function() { + this.controlParentName = "strategy"; + this.inherited(arguments); + this.createChrome(this.listTools); + this.controlParentName = "client"; + this.discoverControlParent(); + }, + createSwipeableComponents: function() { + for(var i=0;i= this.reorderHoldTimeMS) { + // determine if we should handle the hold event + if(this.shouldStartReordering(inSender, inEvent)) { + inEvent.preventDefault(); + this.startReordering(inEvent); + return false; + } + } + }, + //* DragStart event handler + dragstart: function(inSender, inEvent) { + // stop dragstart from propogating if we're in reorder mode + if (this.isReordering()) { + return true; + } + if (this.isSwipeable()) { + return this.swipeDragStart(inSender, inEvent); + } + }, + //* Drag event handler + drag: function(inSender, inEvent) { + // determine if we should handle the drag event + if(this.shouldDoReorderDrag(inEvent)) { + inEvent.preventDefault(); + this.reorderDrag(inEvent); + return true; + } + else if (this.isSwipeable()) { + inEvent.preventDefault(); + this.swipeDrag(inSender, inEvent); + return true; + } + }, + //* Dragfinish event handler + dragfinish: function(inSender, inEvent) { + if(this.isReordering()) { + this.finishReordering(inSender, inEvent); + } + else if (this.isSwipeable()) { + this.swipeDragFinish(inSender, inEvent); + } + }, + //* up event handler + up: function(inSender, inEvent) { + if(this.isReordering()) { + this.finishReordering(inSender, inEvent); + } + }, + generatePage: function(inPageNo, inTarget) { + this.page = inPageNo; + var r = this.rowsPerPage * this.page; + this.$.generator.setRowOffset(r); + var rpp = Math.min(this.count - r, this.rowsPerPage); + this.$.generator.setCount(rpp); + var html = this.$.generator.generateChildHtml(); + inTarget.setContent(html); + // prevent reordering row from being draw twice + if(this.getReorderable() && this.draggingRowIndex > -1) { + this.hideReorderingRow(); + } + var pageHeight = inTarget.getBounds().height; + // if rowHeight is not set, use the height from the first generated page + if (!this.rowHeight && pageHeight > 0) { + this.rowHeight = Math.floor(pageHeight / rpp); + this.updateMetrics(); + } + // update known page heights + if (!this.fixedHeight) { + var h0 = this.getPageHeight(inPageNo); + this.pageHeights[inPageNo] = pageHeight; + this.portSize += pageHeight - h0; + } + }, + //* map a row index number to the page number it would be in + pageForRow: function(inIndex) { + return Math.floor(inIndex / this.rowsPerPage); + }, + // preserve original DOM node because it may be needed to route touch events + preserveDraggingRowNode: function(pageNo) { + if (this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === pageNo) { + this.$.holdingarea.hasNode().appendChild(this.draggingRowNode); + this.draggingRowNode = null; + this.removedInitialPage = true; + } + }, + update: function(inScrollTop) { + var updated = false; + // get page info for position + var pi = this.positionToPageInfo(inScrollTop); + // zone line position + var pos = pi.pos + this.scrollerHeight/2; + // leap-frog zone position + var k = Math.floor(pos/Math.max(pi.height, this.scrollerHeight) + 1/2) + pi.no; + // which page number for page0 (even number pages)? + var p = (k % 2 === 0) ? k : k-1; + if (this.p0 != p && this.isPageInRange(p)) { + this.preserveDraggingRowNode(this.p0); + this.generatePage(p, this.$.page0); + this.positionPage(p, this.$.page0); + this.p0 = p; + updated = true; + this.p0RowBounds = this.getPageRowHeights(this.$.page0); + } + // which page number for page1 (odd number pages)? + p = (k % 2 === 0) ? Math.max(1, k-1) : k; + // position data page 1 + if (this.p1 != p && this.isPageInRange(p)) { + this.preserveDraggingRowNode(this.p1); + this.generatePage(p, this.$.page1); + this.positionPage(p, this.$.page1); + this.p1 = p; + updated = true; + this.p1RowBounds = this.getPageRowHeights(this.$.page1); + } + if (updated) { + // reset generator back to "full-list" values + this.$.generator.setRowOffset(0); + this.$.generator.setCount(this.count); + if (!this.fixedHeight) { + this.adjustBottomPage(); + this.adjustPortSize(); + } + } + }, + getPageRowHeights: function(page) { + var rows = {}; + var allDivs = page.hasNode().querySelectorAll("div[data-enyo-index]"); + for (var i=0, index, bounds; i < allDivs.length; i++) { + index = allDivs[i].getAttribute("data-enyo-index"); + if (index !== null) { + bounds = enyo.dom.getBounds(allDivs[i]); + rows[parseInt(index, 10)] = {height: bounds.height, width: bounds.width}; + } + } + return rows; + }, + updateRowBounds: function(index) { + if (this.p0RowBounds[index]) { + this.updateRowBoundsAtIndex(index, this.p0RowBounds, this.$.page0); + } + else if (this.p1RowBounds[index]) { + this.updateRowBoundsAtIndex(index, this.p1RowBounds, this.$.page1); + } + }, + updateRowBoundsAtIndex: function(index, rows, page) { + var rowDiv = page.hasNode().querySelector('div[data-enyo-index="' + index + '"]'); + var bounds = enyo.dom.getBounds(rowDiv); + rows[index].height = bounds.height; + rows[index].width = bounds.width; + }, + updateForPosition: function(inPos) { + this.update(this.calcPos(inPos)); + }, + calcPos: function(inPos) { + return (this.bottomUp ? (this.portSize - this.scrollerHeight - inPos) : inPos); + }, + adjustBottomPage: function() { + var bp = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; + this.positionPage(bp.pageNo, bp); + }, + adjustPortSize: function() { + this.scrollerHeight = this.getBounds().height; + var s = Math.max(this.scrollerHeight, this.portSize); + this.$.port.applyStyle("height", s + "px"); + }, + positionPage: function(inPage, inTarget) { + inTarget.pageNo = inPage; + var y = this.pageToPosition(inPage); + inTarget.applyStyle(this.pageBound, y + "px"); + }, + pageToPosition: function(inPage) { + var y = 0; + var p = inPage; + while (p > 0) { + p--; + y += this.getPageHeight(p); + } + return y; + }, + positionToPageInfo: function(inY) { + var page = -1; + var p = this.calcPos(inY); + var h = this.defaultPageHeight; + while (p >= 0) { + page++; + h = this.getPageHeight(page); + p -= h; + } + page = Math.max(page, 0); + return { + no: page, + height: h, + pos: p + h, + startRow: (page * this.rowsPerPage), + endRow: Math.min((page + 1) * this.rowsPerPage - 1, this.count - 1) + }; + }, + isPageInRange: function(inPage) { + return inPage == Math.max(0, Math.min(this.pageCount-1, inPage)); + }, + getPageHeight: function(inPageNo) { + var height = this.pageHeights[inPageNo]; + // estimate the height based on how many rows are in this page + if (!height) { + var firstRow = this.rowsPerPage * inPageNo; + var numRows = Math.min(this.count - firstRow, this.rowsPerPage); + height = this.defaultPageHeight * (numRows / this.rowsPerPage); + } + // can never return height of 0, as that would lead to infinite loops + return Math.max(1, height); + }, + invalidatePages: function() { + this.p0 = this.p1 = null; + this.p0RowBounds = {}; + this.p1RowBounds = {}; + // clear the html in our render targets + this.$.page0.setContent(""); + this.$.page1.setContent(""); + }, + invalidateMetrics: function() { + this.pageHeights = []; + this.rowHeight = 0; + this.updateMetrics(); + }, + scroll: function(inSender, inEvent) { + var r = this.inherited(arguments); + var pos = this.getScrollTop(); + if (this.lastPos === pos) { + return r; + } + this.lastPos = pos; + this.update(pos); + if (this.pinnedReorderMode) { + this.reorderScroll(inSender, inEvent); + } + return r; + }, + setScrollTop: function(inScrollTop) { + this.update(inScrollTop); + this.inherited(arguments); + this.twiddle(); + }, + getScrollPosition: function() { + return this.calcPos(this.getScrollTop()); + }, + setScrollPosition: function(inPos) { + this.setScrollTop(this.calcPos(inPos)); + }, + //* @public + //* Scrolls the list so the last item is visible. + scrollToBottom: function() { + this.update(this.getScrollBounds().maxTop); + this.inherited(arguments); + }, + //* Scrolls to the specified row. + scrollToRow: function(inRow) { + var page = this.pageForRow(inRow); + var pageRow = inRow % this.rowsPerPage; + var h = this.pageToPosition(page); + // update the page + this.updateForPosition(h); + // call pageToPosition again and this time should return the right pos since the page info is populated + h = this.pageToPosition(page); + this.setScrollPosition(h); + if (page == this.p0 || page == this.p1) { + var rowNode = this.$.generator.fetchRowNode(inRow); + if (rowNode) { + // calc row offset + var offset = rowNode.offsetTop; + if (this.bottomUp) { + offset = this.getPageHeight(page) - rowNode.offsetHeight - offset; + } + var y = this.getScrollPosition() + offset; + this.setScrollPosition(y); + } + } + }, + //* Scrolls to the beginning of the list. + scrollToStart: function() { + this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); + }, + //* Scrolls to the end of the list. + scrollToEnd: function() { + this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); + }, + //* Re-renders the list at the current position. + refresh: function() { + this.invalidatePages(); + this.update(this.getScrollTop()); + this.stabilize(); + + //FIXME: Necessary evil for Android 4.0.4 refresh bug + if (enyo.platform.android === 4) { + this.twiddle(); + } + }, + /** + Re-renders the list from the beginning. This is used when changing the + data model for the list. This also clears the selection state. + */ + reset: function() { + this.getSelection().clear(); + this.invalidateMetrics(); + this.invalidatePages(); + this.stabilize(); + this.scrollToStart(); + }, + /** + Returns the [enyo.Selection](#enyo.Selection) component that + manages the selection state for this list. + */ + getSelection: function() { + return this.$.generator.getSelection(); + }, + /** + Sets the selection state for the given row index. + _inData_ is an optional data value stored in the selection object. + + Modifying selection will not automatically rerender the row, + so use [renderRow](#enyo.List::renderRow) or [refresh](#enyo.List::refresh) + to update the view. + */ + select: function(inIndex, inData) { + return this.getSelection().select(inIndex, inData); + }, + /** + Clears the selection state for the given row index. + + Modifying selection will not automatically re-render the row, + so use [renderRow](#enyo.List::renderRow) or [refresh](#enyo.List::refresh) + to update the view. + */ + deselect: function(inIndex) { + return this.getSelection().deselect(inIndex); + }, + //* Gets the selection state for the given row index. + isSelected: function(inIndex) { + return this.$.generator.isSelected(inIndex); + }, + /** + Re-renders the specified row. Call this method after making + modifications to a row, to force it to render. + */ + renderRow: function(inIndex) { + this.$.generator.renderRow(inIndex); + }, + //* Updates row bounds when rows are re-rendered. + rowRendered: function(inSender, inEvent) { + this.updateRowBounds(inEvent.rowIndex); + }, + //* Prepares the row to become interactive. + prepareRow: function(inIndex) { + this.$.generator.prepareRow(inIndex); + }, + //* Restores the row to being non-interactive. + lockRow: function() { + this.$.generator.lockRow(); + }, + /** + Performs a set of tasks by running the function _inFunc_ on a row (which + must be interactive at the time the tasks are performed). Locks the row + when done. + */ + performOnRow: function(inIndex, inFunc, inContext) { + this.$.generator.performOnRow(inIndex, inFunc, inContext); + }, + //* @protected + animateFinish: function(inSender) { + this.twiddle(); + return true; + }, + // FIXME: Android 4.04 has issues with nested composited elements; for example, a SwipeableItem, + // can incorrectly generate taps on its content when it has slid off the screen; + // we address this BUG here by forcing the Scroller to "twiddle" which corrects the bug by + // provoking a dom update. + twiddle: function() { + var s = this.getStrategy(); + enyo.call(s, "twiddle"); + }, + // return page0 or page1 control depending on pageNumber odd/even status + pageForPageNumber: function(pageNumber, checkRange) { + if (pageNumber % 2 === 0) { + return (!checkRange || (pageNumber === this.p0)) ? this.$.page0 : null; + } + else { + return (!checkRange || (pageNumber === this.p1)) ? this.$.page1 : null; + } + return null; + }, + /** + ---- Reorder functionality ------------ + */ + //* Determines whether we should handle the hold event as a reorder hold. + shouldStartReordering: function(inSender, inEvent) { + if(!this.getReorderable() || !(inEvent.rowIndex >= 0) || this.pinnedReorderMode || + inSender !== this.$.strategy || !(inEvent.index >= 0)) { + return false; + } + return true; + }, + //* Processes hold event and prepares for reordering. + startReordering: function(inEvent) { + // disable drag to scroll on strategy + this.$.strategy.listReordering = true; + + this.buildReorderContainer(); + this.doSetupReorderComponents(inEvent); + this.styleReorderContainer(inEvent); + + this.draggingRowIndex = this.placeholderRowIndex = inEvent.rowIndex; + this.draggingRowNode = inEvent.target; + this.removedInitialPage = false; + this.itemMoved = false; + this.initialPageNumber = this.currentPageNumber = this.pageForRow(inEvent.rowIndex); + this.prevScrollTop = this.getScrollTop(); + + // fill row being reordered with placeholder + this.replaceNodeWithPlaceholder(inEvent.rowIndex); + }, + /** + Fills reorder container with draggable reorder components defined by the + application. + */ + buildReorderContainer: function() { + this.$.reorderContainer.destroyClientControls(); + for(var i=0;i= this.placeholderRowIndex) { + this.movePlaceholderToIndex(Math.min(this.count, index + 1)); + } + else { + this.movePlaceholderToIndex(index); + } + } + }, + //* Positions the reorder node based on the dx and dy of the drag event. + positionReorderNode: function(e) { + var reorderNodeBounds = this.$.reorderContainer.getBounds(); + var left = reorderNodeBounds.left + e.ddx; + var top = reorderNodeBounds.top + e.ddy; + top = (this.getStrategyKind() == "ScrollStrategy") ? top + (this.getScrollTop() - this.prevScrollTop) : top; + this.$.reorderContainer.addStyles("top: "+top+"px ; left: "+left+"px"); + this.prevScrollTop = this.getScrollTop(); + }, + /** + Checks if the list should scroll when dragging and, if so, starts the + scroll timeout timer. Auto-scrolling happens when the user drags an item + within the top/bottom boundary percentage defined in + _this.dragToScrollThreshold_. + */ + checkForAutoScroll: function(inEvent) { + var position = enyo.dom.calcNodePosition(this.hasNode()); + var bounds = this.getBounds(); + var perc; + this.autoscrollPageY = inEvent.pageY; + if(inEvent.pageY - position.top < bounds.height * this.dragToScrollThreshold) { + perc = 100*(1 - ((inEvent.pageY - position.top) / (bounds.height * this.dragToScrollThreshold))); + this.scrollDistance = -1*perc; + } else if(inEvent.pageY - position.top > bounds.height * (1 - this.dragToScrollThreshold)) { + perc = 100*((inEvent.pageY - position.top - bounds.height*(1 - this.dragToScrollThreshold)) / (bounds.height - (bounds.height * (1 - this.dragToScrollThreshold)))); + this.scrollDistance = 1*perc; + } else { + this.scrollDistance = 0; + } + // stop scrolling if distance is zero (i.e., user isn't scrolling to the edges of + // the list); otherwise, start it if not already started + if (this.scrollDistance === 0) { + this.stopAutoScrolling(); + } else { + if(!this.autoScrollTimeout) { + this.startAutoScrolling(); + } + } + }, + //* Stops auto-scrolling. + stopAutoScrolling: function() { + if(this.autoScrollTimeout) { + clearTimeout(this.autoScrollTimeout); + this.autoScrollTimeout = null; + } + }, + //* Starts auto-scrolling. + startAutoScrolling: function() { + this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); + }, + //* Scrolls the list by the distance specified in _this.scrollDistance_. + autoScroll: function() { + if(this.scrollDistance === 0) { + this.stopAutoScrolling(); + } else { + if(!this.autoScrollTimeout) { + this.startAutoScrolling(); + } + } + this.setScrollPosition(this.getScrollPosition() + this.scrollDistance); + this.positionReorderNode({ddx: 0, ddy: 0}); + + // if the current index the user is dragging over has changed, move the placeholder + this.updatePlaceholderPosition(this.autoscrollPageY); + }, + /** + Moves the placeholder (i.e., the gap between rows) to the row currently + under the user's pointer. This provides a visual cue, showing the user + where the item being dragged will go if it is dropped. + */ + movePlaceholderToIndex: function(index) { + var node, nodeParent; + if (index < 0) { + return; + } + else if (index >= this.count) { + node = null; + nodeParent = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode(); + } + else { + node = this.$.generator.fetchRowNode(index); + nodeParent = node.parentNode; + } + // figure next page for placeholder + var nextPageNumber = this.pageForRow(index); + + // don't add pages beyond the original page count + if(nextPageNumber >= this.pageCount) { + nextPageNumber = this.currentPageNumber; + } + + // move the placeholder to just after our "index" node + nodeParent.insertBefore( + this.placeholderNode, + node); + + if(this.currentPageNumber !== nextPageNumber) { + // if moving to different page, recalculate page heights and reposition pages + this.updatePageHeight(this.currentPageNumber); + this.updatePageHeight(nextPageNumber); + this.updatePagePositions(nextPageNumber); + } + + // save updated state + this.placeholderRowIndex = index; + this.currentPageNumber = nextPageNumber; + + // remember that we moved an item (to prevent pinning at the wrong time) + this.itemMoved = true; + }, + /** + Turns off reordering. If the user didn't drag the item being reordered + outside of its original position, goes into pinned reorder mode. + */ + finishReordering: function(inSender, inEvent) { + if(!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) { + return; + } + this.stopAutoScrolling(); + // enable drag-scrolling on strategy + this.$.strategy.listReordering = false; + // animate reorder container to proper position and then complete + // reordering actions + this.moveReorderedContainerToDroppedPosition(inEvent); + this.completeReorderTimeout = setTimeout( + enyo.bind(this, this.completeFinishReordering, inEvent), 100); + + inEvent.preventDefault(); + return true; + }, + //* + moveReorderedContainerToDroppedPosition: function() { + var offset = this.getRelativeOffset(this.placeholderNode, this.hasNode()); + var top = (this.getStrategyKind() == "ScrollStrategy") ? offset.top : offset.top - this.getScrollTop(); + var left = offset.left - this.getScrollLeft(); + this.positionReorderContainer(left,top); + }, + /** + After the reordered item has been animated to its position, completes + the reordering logic. + */ + completeFinishReordering: function(inEvent) { + this.completeReorderTimeout = null; + // adjust placeholderRowIndex to now be the final resting place + if (this.placeholderRowIndex > this.draggingRowIndex) { + this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1); + } + // if the user dropped the item in the same location where it was picked up, and they + // didn't move any other items in the process, pin the item and go into pinned reorder mode + if(this.draggingRowIndex == this.placeholderRowIndex && + this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { + this.beginPinnedReorder(inEvent); + return; + } + this.removeDraggingRowNode(); + this.removePlaceholderNode(); + this.emptyAndHideReorderContainer(); + // clear this early to prevent scroller code from using disappeared placeholder + this.pinnedReorderMode = false; + this.reorderRows(inEvent); + this.draggingRowIndex = this.placeholderRowIndex = -1; + this.refresh(); + }, + //* Go into pinned reorder mode + beginPinnedReorder: function(e) { + this.buildPinnedReorderContainer(); + this.doSetupPinnedReorderComponents(enyo.mixin(e, {index: this.draggingRowIndex})); + this.pinnedReorderMode = true; + this.initialPinPosition = e.pageY; + }, + //* Clears contents of reorder container, then hides. + emptyAndHideReorderContainer: function() { + this.$.reorderContainer.destroyComponents(); + this.$.reorderContainer.setShowing(false); + }, + //* Fills reorder container with pinned controls. + buildPinnedReorderContainer: function() { + this.$.reorderContainer.destroyClientControls(); + for(var i=0;i 0) ? 1 : -1; + var node, i, newIndex, currentIndex; + + if(direction === 1) { + node = this.$.generator.fetchRowNode(this.draggingRowIndex); + if (node) { + node.setAttribute("data-enyo-index", "reordered"); + } + for(i=(to-1),newIndex=to;i>=from;i--) { + node = this.$.generator.fetchRowNode(i); + if(!node) { + continue; + } + currentIndex = parseInt(node.getAttribute("data-enyo-index"), 10); + newIndex = currentIndex + 1; + node.setAttribute("data-enyo-index", newIndex); + } + node = this.hasNode().querySelector('[data-enyo-index="reordered"]'); + node.setAttribute("data-enyo-index", this.placeholderRowIndex); + + } else { + node = this.$.generator.fetchRowNode(this.draggingRowIndex); + if (node) { + node.setAttribute("data-enyo-index", this.placeholderRowIndex); + } + for(i=(from+1), newIndex=from;i<=to;i++) { + node = this.$.generator.fetchRowNode(i); + if(!node) { + continue; + } + currentIndex = parseInt(node.getAttribute("data-enyo-index"), 10); + newIndex = currentIndex - 1; + node.setAttribute("data-enyo-index", newIndex); + } + } + }, + //* Determines if an item was reordered far enough that it warrants a refresh. + shouldDoRefresh: function() { + return (Math.abs(this.initialPageNumber - this.currentPageNumber) > 1); + }, + //* Gets node height, width, top, and left values. + getNodeStyle: function(index) { + var node = this.$.generator.fetchRowNode(index); + if(!node) { + return; + } + var offset = this.getRelativeOffset(node, this.hasNode()); + var dimensions = enyo.dom.getBounds(node); + return {h: dimensions.height, w: dimensions.width, left: offset.left, top: offset.top}; + }, + //* Gets offset relative to a positioned ancestor node. + getRelativeOffset: function (n, p) { + var ro = {top: 0, left: 0}; + if (n !== p && n.parentNode) { + do { + ro.top += n.offsetTop || 0; + ro.left += n.offsetLeft || 0; + n = n.offsetParent; + } while (n && n !== p); + } + return ro; + }, + replaceNodeWithPlaceholder: function(index) { + var node = this.$.generator.fetchRowNode(index); + if(!node) { + enyo.log("No node - "+index); + return; + } + // create and style placeholder node + this.placeholderNode = this.createPlaceholderNode(node); + // hide existing node + this.hiddenNode = this.hideNode(node); + // insert placeholder node where original node was + var currentPage = this.pageForPageNumber(this.currentPageNumber); + currentPage.hasNode().insertBefore(this.placeholderNode,this.hiddenNode); + }, + /** + Creates and returns a placeholder node with dimensions matching those of + the passed-in node. + */ + createPlaceholderNode: function(node) { + var placeholderNode = this.$.placeholder.hasNode().cloneNode(true); + var nodeDimensions = enyo.dom.getBounds(node); + placeholderNode.style.height = nodeDimensions.height + "px"; + placeholderNode.style.width = nodeDimensions.width + "px"; + return placeholderNode; + }, + //* Removes the placeholder node from the DOM. + removePlaceholderNode: function() { + this.removeNode(this.placeholderNode); + this.placeholderNode = null; + }, + removeDraggingRowNode: function() { + this.draggingRowNode = null; + var holdingArea = this.$.holdingarea.hasNode(); + holdingArea.innerHTML = ""; + }, + //* Removes the passed-in node from the DOM. + removeNode: function(node) { + if(!node || !node.parentNode) { + return; + } + node.parentNode.removeChild(node); + }, + /** + Updates _this.pageHeights_ to support the placeholder node's jumping + from one page to the next. + */ + updatePageHeight: function(pageNumber) { + if (pageNumber < 0) { + return; + } + var pageControl = this.pageForPageNumber(pageNumber, true); + if (pageControl) { + var h0 = this.pageHeights[pageNumber]; + var pageHeight = Math.max(1, pageControl.getBounds().height); + this.pageHeights[pageNumber] = pageHeight; + this.portSize += pageHeight - h0; + } + }, + /** + Repositions the two passed-in pages to support the placeholder node's + jumping from one page to the next. + */ + updatePagePositions: function(nextPageNumber) { + this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)); + this.positionPage(nextPageNumber, this.pageForPageNumber(nextPageNumber)); + }, + //* Corrects page heights array after reorder is complete. + correctPageHeights: function() { + this.updatePageHeight(this.currentPageNumber); + if (this.initialPageNumber != this.currentPageNumber) { + this.updatePageHeight(this.initialPageNumber); + } + }, + hideNode: function(node) { + node.style.display = "none"; + return node; + }, + showNode: function(node) { + node.style.display = "block"; + return node; + }, + //* @public + //* Called by client code to finalize a pinned mode reordering, such as when the "Drop" button is pressed + //* on the pinned placeholder row. + dropPinnedRow: function(inEvent) { + // animate reorder container to proper position and then complete reording actions + this.moveReorderedContainerToDroppedPosition(inEvent); + this.completeReorderTimeout = setTimeout( + enyo.bind(this, this.completeFinishReordering, inEvent), 100); + return; + }, + cancelPinnedMode: function(inEvent) { + // make it look like we're dropping in original location + this.placeholderRowIndex = this.draggingRowIndex; + this.dropPinnedRow(inEvent); + }, + //* @protected + //* Returns the row index that is under the given position on the page. If the + //* position is off the end of the list, this will return this.count. If the position + //* is before the start of the list, you'll get -1. + getRowIndexFromCoordinate: function(y) { + var cursorPosition = this.getScrollTop() + y - enyo.dom.calcNodePosition(this.hasNode()).top; + // happens if we try to drag past top of list + if (cursorPosition < 0) { + return -1; + } + var pageInfo = this.positionToPageInfo(cursorPosition); + var rows = (pageInfo.no == this.p0) ? this.p0RowBounds : this.p1RowBounds; + // might have only rendered one page, so catch that here + if (!rows) { + return this.count; + } + var posOnPage = pageInfo.pos; + var placeholderHeight = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0; + var totalHeight = 0; + for(var i=pageInfo.startRow; i <= pageInfo.endRow; ++i) { + // do extra check for row that has placeholder as we'll return -1 here for no match + if (i === this.placeholderRowIndex) { + // for placeholder + totalHeight += placeholderHeight; + if(totalHeight >= posOnPage) { + return -1; + } + } + // originally dragged row is hidden, so don't count it + if (i !== this.draggingRowIndex) { + totalHeight += rows[i].height; + if(totalHeight >= posOnPage) { + return i; + } + } + } + return i; + }, + //* Gets the position of a node (identified via index) on the page. + getIndexPosition: function(index) { + return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(index)); + }, + //* Sets _$item_'s position to match that of the list row at _index_. + setItemPosition: function($item,index) { + var clonedNodeStyle = this.getNodeStyle(index); + var top = (this.getStrategyKind() == "ScrollStrategy") ? clonedNodeStyle.top : clonedNodeStyle.top - this.getScrollTop(); + var styleStr = "top:"+top+"px; left:"+clonedNodeStyle.left+"px;"; + $item.addStyles(styleStr); + }, + //* Sets _$item_'s width and height to match those of the list row at _index_. + setItemBounds: function($item,index) { + var clonedNodeStyle = this.getNodeStyle(index); + var styleStr = "width:"+clonedNodeStyle.w+"px; height:"+clonedNodeStyle.h+"px;"; + $item.addStyles(styleStr); + }, + /** + When in pinned reorder mode, repositions the pinned placeholder when the + user has scrolled far enough. + */ + reorderScroll: function(inSender, e) { + // if we are using the standard scroll strategy, we have to move the pinned row with the scrolling + if(this.getStrategyKind() == "ScrollStrategy") { + this.$.reorderContainer.addStyles("top:"+(this.initialPinPosition+this.getScrollTop()-this.rowHeight)+"px;"); + } + // y coordinate on screen of the pinned item doesn't change as we scroll things + this.updatePlaceholderPosition(this.initialPinPosition); + }, + hideReorderingRow: function() { + var hiddenNode = this.hasNode().querySelector('[data-enyo-index="'+this.draggingRowIndex+'"]'); + // hide existing node + if(hiddenNode) { + this.hiddenNode = this.hideNode(hiddenNode); + } + }, + isReordering: function() { + return (this.draggingRowIndex > -1); + }, + + /** + ---- Swipeable functionality ------------ + */ + + isSwiping: function() { + // we're swiping when the index is set and we're not in the middle of completing or backing out a swipe + return (this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null); + }, + /** + When a drag starts, gets the direction of the drag as well as the index + of the item being dragged, and resets any pertinent values. Then kicks + off the swipe sequence. + */ + swipeDragStart: function(inSender, inEvent) { + // if we're not on a row or the swipe is vertical or if we're in the middle of reordering, just say no + if(inEvent.index == null || inEvent.vertical) { + return true; + } + + // if we are waiting to complete a swipe, complete it + if(this.completeSwipeTimeout) { + this.completeSwipe(inEvent); + } + + // reset swipe complete flag + this.swipeComplete = false; + + if (this.swipeIndex != inEvent.index) { + this.clearSwipeables(); + this.swipeIndex = inEvent.index; + } + this.swipeDirection = inEvent.xDirection; + + // start swipe sequence only if we are not currently showing a persistent item + if(!this.persistentItemVisible) { + this.startSwipe(inEvent); + } + + // reset dragged distance (for dragfinish) + this.draggedXDistance = 0; + this.draggedYDistance = 0; + + return true; + }, + /** + When a drag is in progress, updates the position of the swipeable + container based on the ddx of the event. + */ + swipeDrag: function(inSender, inEvent) { + // if a persistent swipeableItem is still showing, handle it separately + if (this.persistentItemVisible) { + this.dragPersistentItem(inEvent); + return this.preventDragPropagation; + } + // early exit if there's no matching dragStart to set item + if (!this.isSwiping()) { + return false; + } + // apply new position + this.dragSwipeableComponents(this.calcNewDragPosition(inEvent.ddx)); + // save dragged distance (for dragfinish) + this.draggedXDistance = inEvent.dx; + this.draggedYDistance = inEvent.dy; + return true; + }, + /* + When the current drag completes, decides whether to complete the swipe + based on how far the user pulled the swipeable container. + */ + swipeDragFinish: function(inSender, inEvent) { + // if a persistent swipeableItem is still showing, complete drag away or bounce + if (this.persistentItemVisible) { + this.dragFinishPersistentItem(inEvent); + // early exit if there's no matching dragStart to set item + } else if (!this.isSwiping()) { + return false; + // otherwise if user dragged more than 20% of the width, complete the swipe. if not, back out. + } else { + var percentageDragged = this.calcPercentageDragged(this.draggedXDistance); + if ((percentageDragged > this.percentageDraggedThreshold) && (inEvent.xDirection === this.swipeDirection)) { + this.swipe(this.fastSwipeSpeedMS); + } else { + this.backOutSwipe(inEvent); + } + } + + return this.preventDragPropagation; + }, + // reorder takes precedence over swipes, and not having it turned on or swipeable controls defined also disables this + isSwipeable: function() { + return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && + !this.isReordering() && !this.pinnedReorderMode; + }, + // Positions the swipeable components block at the current row. + positionSwipeableContainer: function(index,xDirection) { + var node = this.$.generator.fetchRowNode(index); + if(!node) { + return; + } + var offset = this.getRelativeOffset(node, this.hasNode()); + var dimensions = enyo.dom.getBounds(node); + var x = (xDirection == 1) ? -1*dimensions.width : dimensions.width; + this.$.swipeableComponents.addStyles("top: "+offset.top+"px; left: "+x+"px; height: "+dimensions.height+"px; width: "+dimensions.width+"px;"); + }, + /** + Calculates new position for the swipeable container based on the user's + drag action. Don't allow the container to drag beyond either edge. + */ + calcNewDragPosition: function(dx) { + var parentBounds = this.$.swipeableComponents.getBounds(); + var xPos = parentBounds.left; + var dimensions = this.$.swipeableComponents.getBounds(); + var xlimit = (this.swipeDirection == 1) ? 0 : -1*dimensions.width; + var x = (this.swipeDirection == 1) + ? (xPos + dx > xlimit) + ? xlimit + : xPos + dx + : (xPos + dx < xlimit) + ? xlimit + : xPos + dx; + return x; + }, + dragSwipeableComponents: function(x) { + this.$.swipeableComponents.applyStyle("left",x+"px"); + }, + /** + Begins swiping sequence by positioning the swipeable container and + bubbling the setupSwipeItem event. + */ + startSwipe: function(e) { + // modify event index to always have this swipeItem value + e.index = this.swipeIndex; + this.positionSwipeableContainer(this.swipeIndex,e.xDirection); + this.$.swipeableComponents.setShowing(true); + this.setPersistentItemOrigin(e.xDirection); + this.doSetupSwipeItem(e); + }, + // If a persistent swipeableItem is still showing, drags it away or bounces it. + dragPersistentItem: function(e) { + var xPos = 0; + var x = (this.persistentItemOrigin == "right") + ? Math.max(xPos, (xPos + e.dx)) + : Math.min(xPos, (xPos + e.dx)); + this.$.swipeableComponents.applyStyle("left",x+"px"); + }, + // If a persistent swipeableItem is still showing, completes drag away or bounce. + dragFinishPersistentItem: function(e) { + var completeSwipe = (this.calcPercentageDragged(e.dx) > 0.2); + var dir = (e.dx > 0) ? "right" : (e.dx < 0) ? "left" : null; + if(this.persistentItemOrigin == dir) { + if(completeSwipe) { + this.slideAwayItem(); + } else { + this.bounceItem(e); + } + } else { + this.bounceItem(e); + } + }, + setPersistentItemOrigin: function(xDirection) { + this.persistentItemOrigin = xDirection == 1 ? "left" : "right"; + }, + calcPercentageDragged: function(dx) { + return Math.abs(dx/this.$.swipeableComponents.getBounds().width); + }, + swipe: function(speed) { + this.swipeComplete = true; + this.animateSwipe(0,speed); + }, + backOutSwipe: function(e) { + var dimensions = this.$.swipeableComponents.getBounds(); + var x = (this.swipeDirection == 1) ? -1*dimensions.width : dimensions.width; + this.animateSwipe(x,this.fastSwipeSpeedMS); + this.swipeDirection = null; + }, + bounceItem: function(e) { + var bounds = this.$.swipeableComponents.getBounds(); + if(bounds.left != bounds.width) { + this.animateSwipe(0,this.normalSwipeSpeedMS); + } + }, + slideAwayItem: function() { + var $item = this.$.swipeableComponents; + var parentWidth = $item.getBounds().width; + var xPos = (this.persistentItemOrigin == "left") ? -1*parentWidth : parentWidth; + this.animateSwipe(xPos,this.normalSwipeSpeedMS); + this.persistentItemVisible = false; + this.setPersistSwipeableItem(false); + }, + clearSwipeables: function() { + this.$.swipeableComponents.setShowing(false); + this.persistentItemVisible = false; + this.setPersistSwipeableItem(false); + }, + // Completes swipe and hides active swipeable item. + completeSwipe: function(e) { + if(this.completeSwipeTimeout) { + clearTimeout(this.completeSwipeTimeout); + this.completeSwipeTimeout = null; + } + // if this wasn't a persistent item, hide it upon completion and send swipe complete event + if(!this.getPersistSwipeableItem()) { + this.$.swipeableComponents.setShowing(false); + // if the swipe was completed, update the current row and bubble swipeComplete event + if(this.swipeComplete) { + this.doSwipeComplete({index: this.swipeIndex, xDirection: this.swipeDirection}); + } + } else { + this.persistentItemVisible = true; + } + this.swipeIndex = null; + this.swipeDirection = null; + }, + animateSwipe: function(targetX,totalTimeMS) { + var t0 = enyo.now(), t = 0; + var $item = this.$.swipeableComponents; + var origX = parseInt($item.domStyles.left,10); + var xDelta = targetX - origX; + + this.stopAnimateSwipe(); + + var fn = enyo.bind(this, function() { + var t = enyo.now() - t0; + var percTimeElapsed = t/totalTimeMS; + var currentX = origX + (xDelta)*Math.min(percTimeElapsed,1); + + // set new left + $item.applyStyle("left",currentX+"px"); + + // schedule next frame + this.job = enyo.requestAnimationFrame(fn); + + // potentially override animation TODO + + // go until we've hit our total time + if(t/totalTimeMS >= 1) { + this.stopAnimateSwipe(); + this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { + this.completeSwipe(); + }), this.completeSwipeDelayMS); + } + }); + + this.job = enyo.requestAnimationFrame(fn); + }, + stopAnimateSwipe: function() { + if(this.job) { + this.job = enyo.cancelRequestAnimationFrame(this.job); + } + } +}); \ No newline at end of file diff --git a/lib/layout/list/source/PulldownList.css b/lib/layout/list/source/PulldownList.css new file mode 100644 index 0000000..89f6da0 --- /dev/null +++ b/lib/layout/list/source/PulldownList.css @@ -0,0 +1,60 @@ +.enyo-list-pulldown { + position: absolute; + bottom: 100%; + left: 0; + right: 0; +} + +.enyo-puller { + position: relative; + height: 50px; + font-size: 22px; + color: #444; + padding: 20px 0 0px 34px; +} + +.enyo-puller-text { + position: absolute; + left: 80px; + top: 22px; +} + +.enyo-puller-arrow { + position: relative; + background: #444; + width: 7px; + height: 28px; + transition: transform 0.3s; + -webkit-transition: -webkit-transform 0.3s; + -moz-transition: -moz-transform 0.3s; + -o-transition: -o-transform 0.3s; + -ms-transition: -ms-transform 0.3s; +} + +.enyo-puller-arrow:after { + content: " "; + height: 0; + width: 0; + position: absolute; + border: 10px solid transparent; + border-bottom-color: #444; + bottom: 100%; + left: 50%; + margin-left: -10px; +} + +.enyo-puller-arrow-up { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); +} + +.enyo-puller-arrow-down { + transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -o-transform: rotate(180deg); + -ms-transform: rotate(180deg); +} \ No newline at end of file diff --git a/lib/layout/list/source/PulldownList.js b/lib/layout/list/source/PulldownList.js new file mode 100644 index 0000000..88e13c4 --- /dev/null +++ b/lib/layout/list/source/PulldownList.js @@ -0,0 +1,202 @@ +/** +_enyo.PulldownList_ is a list that provides a pull-to-refresh feature, which +allows new data to be retrieved and updated in the list. + +PulldownList provides the _onPullRelease_ event to allow an application to start +retrieving new data. The _onPullComplete_ event indicates that the pull is +complete and it's time to update the list with the new data. + + {name: "list", kind: "PulldownList", onSetupItem: "setupItem", + onPullRelease: "pullRelease", onPullComplete: "pullComplete", + components: [ + {name: "item"} + ]} + + pullRelease: function() { + this.search(); + }, + processSearchResults: function(inRequest, inResponse) { + this.results = inResponse.results; + this.$.list.setCount(this.results.length); + this.$.list.completePull(); + }, + pullComplete: function() { + this.$.list.reset(); + } +*/ +enyo.kind({ + name: "enyo.PulldownList", + kind: "List", + //* @protected + // Sets touch to true in inherited Scroller kind for touch-based scrolling strategy + touch: true, + // The pull notification area at the top of the list + pully: null, + pulldownTools: [ + {name: "pulldown", classes: "enyo-list-pulldown", components: [ + {name: "puller", kind: "Puller"} + ]} + ], + events: { + //* Fires when user initiates a pull action. + onPullStart: "", + //* Fires when user cancels a pull action. + onPullCancel: "", + //* Fires while a pull action is in progress. + onPull: "", + //* Fires when the list is released following a pull action, indicating + //* that we are ready to retrieve data. + onPullRelease: "", + //* Fires when data retrieval is complete, indicating that the data is + //* is ready to be displayed. + onPullComplete: "" + }, + handlers: { + onScrollStart: "scrollStartHandler", + onScrollStop: "scrollStopHandler", + ondragfinish: "dragfinish" + }, + //* Message displayed when list is not being pulled + pullingMessage: "Pull down to refresh...", + //* Message displayed while a pull action is in progress + pulledMessage: "Release to refresh...", + //* Message displayed while data is being retrieved + loadingMessage: "Loading...", + // + pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", + pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", + loadingIconClass: "", + //* @protected + create: function() { + var p = {kind: "Puller", showing: false, text: this.loadingMessage, iconClass: this.loadingIconClass, onCreate: "setPully"}; + this.listTools.splice(0, 0, p); + this.inherited(arguments); + this.setPulling(); + }, + initComponents: function() { + this.createChrome(this.pulldownTools); + this.accel = enyo.dom.canAccelerate(); + this.translation = this.accel ? "translate3d" : "translate"; + this.strategyKind = this.resetStrategyKind(); + this.inherited(arguments); + }, + // Temporarily use TouchScrollStrategy on iOS devices (see ENYO-1714) + resetStrategyKind: function() { + return (enyo.platform.android >= 3) + ? "TranslateScrollStrategy" + : "TouchScrollStrategy"; + }, + setPully: function(inSender, inEvent) { + this.pully = inEvent.originator; + }, + scrollStartHandler: function() { + this.firedPullStart = false; + this.firedPull = false; + this.firedPullCancel = false; + }, + scroll: function(inSender, inEvent) { + var r = this.inherited(arguments); + if (this.completingPull) { + this.pully.setShowing(false); + } + var s = this.getStrategy().$.scrollMath || this.getStrategy(); + var over = -1*this.getScrollTop(); + if (s.isInOverScroll() && over > 0) { + enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + over + "px" + (this.accel ? ",0" : "")); + if (!this.firedPullStart) { + this.firedPullStart = true; + this.pullStart(); + this.pullHeight = this.$.pulldown.getBounds().height; + } + if (over > this.pullHeight && !this.firedPull) { + this.firedPull = true; + this.firedPullCancel = false; + this.pull(); + } + if (this.firedPull && !this.firedPullCancel && over < this.pullHeight) { + this.firedPullCancel = true; + this.firedPull = false; + this.pullCancel(); + } + } + return r; + }, + scrollStopHandler: function() { + if (this.completingPull) { + this.completingPull = false; + this.doPullComplete(); + } + }, + dragfinish: function() { + if (this.firedPull) { + var s = this.getStrategy().$.scrollMath || this.getStrategy(); + s.setScrollY(-1*this.getScrollTop() - this.pullHeight); + this.pullRelease(); + } + }, + //* @public + //* Signals that the list should execute pull completion. This is usually + //* called after the application has received the new data. + completePull: function() { + this.completingPull = true; + var s = this.getStrategy().$.scrollMath || this.getStrategy(); + s.setScrollY(this.pullHeight); + s.start(); + }, + //* @protected + pullStart: function() { + this.setPulling(); + this.pully.setShowing(false); + this.$.puller.setShowing(true); + this.doPullStart(); + }, + pull: function() { + this.setPulled(); + this.doPull(); + }, + pullCancel: function() { + this.setPulling(); + this.doPullCancel(); + }, + pullRelease: function() { + this.$.puller.setShowing(false); + this.pully.setShowing(true); + this.doPullRelease(); + }, + setPulling: function() { + this.$.puller.setText(this.pullingMessage); + this.$.puller.setIconClass(this.pullingIconClass); + }, + setPulled: function() { + this.$.puller.setText(this.pulledMessage); + this.$.puller.setIconClass(this.pulledIconClass); + } +}); + +enyo.kind({ + name: "enyo.Puller", + classes: "enyo-puller", + published: { + text: "", + iconClass: "" + }, + events: { + onCreate: "" + }, + components: [ + {name: "icon"}, + {name: "text", tag: "span", classes: "enyo-puller-text"} + ], + create: function() { + this.inherited(arguments); + this.doCreate(); + this.textChanged(); + this.iconClassChanged(); + }, + textChanged: function() { + this.$.text.setContent(this.text); + }, + iconClassChanged: function() { + this.$.icon.setClasses(this.iconClass); + } +}); \ No newline at end of file diff --git a/lib/layout/list/source/package.js b/lib/layout/list/source/package.js new file mode 100644 index 0000000..b00e27f --- /dev/null +++ b/lib/layout/list/source/package.js @@ -0,0 +1,8 @@ +enyo.depends( + "FlyweightRepeater.js", + "List.css", + "List.js", + "PulldownList.css", + "PulldownList.js", + "AroundList.js" +); \ No newline at end of file diff --git a/lib/layout/list/source/wip-package.js b/lib/layout/list/source/wip-package.js new file mode 100644 index 0000000..bafc093 --- /dev/null +++ b/lib/layout/list/source/wip-package.js @@ -0,0 +1,6 @@ +enyo.depends( + // Add wip controls here + "AlphaJumper.css", + "AlphaJumper.js", + "AlphaJumpList.js" +); \ No newline at end of file diff --git a/lib/layout/package.js b/lib/layout/package.js new file mode 100644 index 0000000..a796319 --- /dev/null +++ b/lib/layout/package.js @@ -0,0 +1,8 @@ +enyo.depends( + "fittable", + "list", + "slideable", + "panels", + "tree", + "imageview" +); diff --git a/lib/layout/panels/package.js b/lib/layout/panels/package.js new file mode 100644 index 0000000..f1de4f2 --- /dev/null +++ b/lib/layout/panels/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "source/" +); \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.css b/lib/layout/panels/samples/PanelsFlickrSample.css new file mode 100644 index 0000000..8855c8e --- /dev/null +++ b/lib/layout/panels/samples/PanelsFlickrSample.css @@ -0,0 +1,72 @@ +.panels-sample-flickr-panels { + color: white; + background: #555; +} +.panels-sample-flickr-panels > * { + width: 320px; + box-shadow: -4px 0px 4px rgba(0,0,0,0.3); + -moz-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); + -webkit-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); +} +.panels-sample-flickr-item { + position: relative; + border-bottom: 1px solid #0E0E0E; + padding: 12px 16px; + background-color: #333333; +} + +.panels-sample-flickr-item.onyx-selected { + background-color: MidnightBlue; +} + +.panels-sample-flickr-title { + position: absolute; + top: 40px; + right: 0; + left: 100px; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.panels-sample-flickr-thumbnail { + width: 75px; + height: 75px; +} +.panels-sample-flickr-more-button { + color: white; margin: 10px; +} +.panels-sample-flickr-more-spinner { + vertical-align: middle; + margin: -4px 0 0 4px; +} +.panels-sample-flickr-center { + margin: auto; +} +.panels-sample-flickr-main { + background-color: #333; +} +.panels-sample-flickr-image { + box-sizing: border-box; + max-height: 90%; + max-width: 90%; + border: solid 5px #CCC; + box-shadow: 1px 1px 5px #999; + width: auto; + height: auto; +} + +.panels-sample-flickr-image.wide { + width: 100%; +} + + +@media all and (max-width: 800px) { + .panels-sample-flickr-image.wide { + width: auto; + } +} + +.panels-sample-flickr-image.tall { + height: 100%; +} \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.html b/lib/layout/panels/samples/PanelsFlickrSample.html new file mode 100644 index 0000000..5e0be21 --- /dev/null +++ b/lib/layout/panels/samples/PanelsFlickrSample.html @@ -0,0 +1,23 @@ + + + + + Panels Flickr App Example + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.js b/lib/layout/panels/samples/PanelsFlickrSample.js new file mode 100644 index 0000000..b4177df --- /dev/null +++ b/lib/layout/panels/samples/PanelsFlickrSample.js @@ -0,0 +1,152 @@ +enyo.kind({ + name: "enyo.sample.PanelsFlickrSample", + kind: "Panels", + classes: "panels-sample-flickr-panels enyo-unselectable enyo-fit", + arrangerKind: "CollapsingArranger", + components: [ + {layoutKind: "FittableRowsLayout", components: [ + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.InputDecorator", style: "width: 90%;", layoutKind: "FittableColumnsLayout", components: [ + {name: "searchInput", fit: true, kind: "onyx.Input", value: "Japan", onchange: "search"}, + {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px; height: 20px;"} + ]}, + {name: "searchSpinner", kind: "Image", src: "assets/spinner.gif", showing: false} + ]}, + {kind: "List", fit: true, touch: true, onSetupItem: "setupItem", components: [ + {name: "item", style: "padding: 10px;", classes: "panels-sample-flickr-item enyo-border-box", ontap: "itemTap", components: [ + {name: "thumbnail", kind: "Image", classes: "panels-sample-flickr-thumbnail"}, + {name: "title", classes: "panels-sample-flickr-title"} + ]}, + {name: "more", style: "background-color: #323232;", components: [ + {kind: "onyx.Button", content: "more photos", classes: "onyx-dark panels-sample-flickr-more-button", ontap: "more"}, + {name: "moreSpinner", kind: "Image", src: "assets/spinner.gif", classes: "panels-sample-flickr-more-spinner"} + ]} + ]} + ]}, + {name: "pictureView", fit: true, kind: "FittableRows", classes: "enyo-fit panels-sample-flickr-main", components: [ + {name: "backToolbar", kind: "onyx.Toolbar", showing: false, components: [ + {kind: "onyx.Button", content: "Back", ontap: "showList"} + ]}, + {fit: true, style: "position: relative;", components: [ + {name: "flickrImage", kind: "Image", classes: "enyo-fit panels-sample-flickr-center panels-sample-flickr-image", showing: false, onload: "imageLoaded", onerror: "imageLoaded"}, + {name: "imageSpinner", kind: "Image", src: "assets/spinner-large.gif", classes: "enyo-fit panels-sample-flickr-center", showing: false} + ]} + ]}, + {kind: "FlickrSearch", onResults: "searchResults"} + ], + rendered: function() { + this.inherited(arguments); + this.search(); + }, + reflow: function() { + this.inherited(arguments); + var backShowing = this.$.backToolbar.showing; + this.$.backToolbar.setShowing(enyo.Panels.isScreenNarrow()); + if (this.$.backToolbar.showing != backShowing) { + this.$.pictureView.resized(); + } + }, + search: function() { + this.searchText = this.$.searchInput.getValue(); + this.page = 0; + this.results = []; + this.$.searchSpinner.show(); + this.$.flickrSearch.search(this.searchText); + }, + searchResults: function(inSender, inResults) { + this.$.searchSpinner.hide(); + this.$.moreSpinner.hide(); + this.results = this.results.concat(inResults); + this.$.list.setCount(this.results.length); + if (this.page === 0) { + this.$.list.reset(); + } else { + this.$.list.refresh(); + } + }, + setupItem: function(inSender, inEvent) { + var i = inEvent.index; + var item = this.results[i]; + this.$.item.addRemoveClass("onyx-selected", inSender.isSelected(inEvent.index)); + this.$.thumbnail.setSrc(item.thumbnail); + this.$.title.setContent(item.title || "Untitled"); + this.$.more.canGenerate = !this.results[i+1]; + }, + more: function() { + this.page++; + this.$.moreSpinner.show(); + this.$.flickrSearch.search(this.searchText, this.page); + }, + itemTap: function(inSender, inEvent) { + if (enyo.Panels.isScreenNarrow()) { + this.setIndex(1); + } + this.$.imageSpinner.show(); + var item = this.results[inEvent.index]; + + if (item.original == this.$.flickrImage.getSrc()) { + this.imageLoaded(); + } else { + this.$.flickrImage.hide(); + this.$.flickrImage.setSrc(item.original); + } + }, + imageLoaded: function() { + var img = this.$.flickrImage; + img.removeClass("tall"); + img.removeClass("wide"); + img.show(); + var b = img.getBounds(); + var r = b.height / b.width; + if (r >= 1.25) { + img.addClass("tall"); + } else if (r <= 0.8 ) { + img.addClass("wide"); + } + this.$.imageSpinner.hide(); + }, + showList: function() { + this.setIndex(0); + } +}); + +// A simple component to do a Flickr search. +enyo.kind({ + name: "FlickrSearch", + kind: "Component", + published: { + searchText: "" + }, + events: { + onResults: "" + }, + url: "http://api.flickr.com/services/rest/", + pageSize: 200, + api_key: "2a21b46e58d207e4888e1ece0cb149a5", + search: function(inSearchText, inPage) { + this.searchText = inSearchText || this.searchText; + var i = (inPage || 0) * this.pageSize; + var params = { + method: "flickr.photos.search", + format: "json", + api_key: this.api_key, + per_page: this.pageSize, + page: i, + text: this.searchText + }; + return new enyo.JsonpRequest({url: this.url, callbackName: "jsoncallback"}) + .response(this, "processResponse") + .go(params) + ; + }, + processResponse: function(inSender, inResponse) { + var photos = inResponse.photos ? inResponse.photos.photo || [] : []; + for (var i=0, p; (p=photos[i]); i++) { + var urlprefix = "http://farm" + p.farm + ".static.flickr.com/" + p.server + "/" + p.id + "_" + p.secret; + p.thumbnail = urlprefix + "_s.jpg"; + p.original = urlprefix + ".jpg"; + } + this.doResults(photos); + return photos; + } +}); diff --git a/lib/layout/panels/samples/PanelsSample.css b/lib/layout/panels/samples/PanelsSample.css new file mode 100644 index 0000000..fed08d2 --- /dev/null +++ b/lib/layout/panels/samples/PanelsSample.css @@ -0,0 +1,40 @@ +.panels-sample-panels { + min-height: 320px; + min-width: 320px; +} + +.panels-sample-panels > * { + border: 2px solid #333; + font-size: 5em; + text-align: center; +} + +.panels-sample-wide > * { + min-width: 50%; +} + +.panels-sample-collapsible > * { + min-width: 250px; +} + +.panels-sample-spiral > * { + min-width:150px; + min-height:150px; + max-height:150px; + max-width:150px; +} + +.panels-sample-grid > * { + min-width:150px; + min-height:150px; + max-height:150px; + max-width:150px; +} +.arranger-scroller { +} + +@media screen and (max-width: 480px) { + .arranger-scroller { + max-height: 270px; + } +} diff --git a/lib/layout/panels/samples/PanelsSample.html b/lib/layout/panels/samples/PanelsSample.html new file mode 100644 index 0000000..a28c3a1 --- /dev/null +++ b/lib/layout/panels/samples/PanelsSample.html @@ -0,0 +1,23 @@ + + + + + Panels Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSample.js b/lib/layout/panels/samples/PanelsSample.js new file mode 100644 index 0000000..973cb61 --- /dev/null +++ b/lib/layout/panels/samples/PanelsSample.js @@ -0,0 +1,108 @@ +enyo.kind({ + name: "enyo.sample.MyGridArranger", + kind: "GridArranger", + colHeight: "150", + colWidth: "150" +}); + +enyo.kind({ + name: "enyo.sample.PanelsSample", + kind: "FittableRows", + classes: "enyo-fit", + components: [ + {kind: "FittableColumns", noStretch: true, classes: "onyx-toolbar onyx-toolbar-inline", components: [ + {kind: "Scroller", thumb: false, fit: true, touch: true, vertical: "hidden", style: "margin: 0;", components: [ + {classes: "onyx-toolbar-inline", style: "white-space: nowrap;", components: [ + {kind: "onyx.MenuDecorator", components: [ + {content:"Arranger"}, + {name:"arrangerPicker", kind: "onyx.Menu", maxHeight: 360, floating: true, onSelect:"arrangerSelected"} + ]}, + {kind: "onyx.Button", content: "Previous", ontap: "prevPanel"}, + {kind: "onyx.Button", content: "Next", ontap: "nextPanel"}, + {kind: "onyx.InputDecorator", style: "width: 60px;", components: [ + {kind: "onyx.Input", value: 0, onchange: "gotoPanel"} + ]}, + {kind: "onyx.Button", content: "Go", ontap: "gotoPanel"}, + {kind: "onyx.Button", content: "Add", ontap: "addPanel"}, + {kind: "onyx.Button", content: "Delete", ontap: "deletePanel"} + ]} + ]} + ]}, + {kind: "Panels", name:"samplePanels", fit:true, realtimeFit: true, classes: "panels-sample-panels enyo-border-box", components: [ + {content:0, style:"background:red;"}, + {content:1, style:"background:orange;"}, + {content:2, style:"background:yellow;"}, + {content:3, style:"background:green;"}, + {content:4, style:"background:blue;"}, + {content:5, style:"background:indigo;"}, + {content:6, style:"background:violet;"} + ]} + ], + panelArrangers: [ + {name: "CardArranger", arrangerKind: "CardArranger"}, + {name: "CardSlideInArranger", arrangerKind: "CardSlideInArranger"}, + {name: "CarouselArranger", arrangerKind: "CarouselArranger", classes: "panels-sample-wide"}, + {name: "CollapsingArranger", arrangerKind: "CollapsingArranger", classes: "panels-sample-collapsible"}, + {name: "LeftRightArranger", arrangerKind: "LeftRightArranger"}, + {name: "TopBottomArranger", arrangerKind: "TopBottomArranger", classes: "panels-sample-topbottom"}, + {name: "SpiralArranger", arrangerKind: "SpiralArranger", classes: "panels-sample-spiral"}, + {name: "GridArranger", arrangerKind: "enyo.sample.MyGridArranger", classes: "panels-sample-grid"}, + {name: "DockRightArranger", arrangerKind: "DockRightArranger", classes: "panels-sample-collapsible"} + ], + bgcolors: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"], + create: function() { + this.inherited(arguments); + for (var i=0; i * { + width: 320px; + background-color: #EAEAEA; + -moz-box-shadow: -4px 0 4px rgba(0,0,0,0.3); + -webkit-box-shadow: -4px 0 4px rgba(0,0,0,0.3); + box-shadow: -4px 0 4px rgba(0,0,0,0.3); +} + +.panels-sample-sliding-item { + padding: 10px; + border-bottom: 1px solid black; +} + +.panels-sample-sliding-content { + text-align: left; + padding: 10px; +} \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSlidingSample.html b/lib/layout/panels/samples/PanelsSlidingSample.html new file mode 100644 index 0000000..f0644c0 --- /dev/null +++ b/lib/layout/panels/samples/PanelsSlidingSample.html @@ -0,0 +1,23 @@ + + + + + Panels Sliding App Example + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSlidingSample.js b/lib/layout/panels/samples/PanelsSlidingSample.js new file mode 100644 index 0000000..a1fb7e8 --- /dev/null +++ b/lib/layout/panels/samples/PanelsSlidingSample.js @@ -0,0 +1,35 @@ +enyo.kind({ + name: "enyo.sample.PanelsSlidingSample", + kind: "FittableRows", + classes: "onyx enyo-fit", + components: [ + {kind: "onyx.Toolbar", components: [ + {content: "Realtime"}, + {kind: "onyx.Checkbox", onchange: "checkboxChange"} + ]}, + {kind: "Panels", fit: true, classes: "panels-sample-sliding-panels", arrangerKind: "CollapsingArranger", wrap: false, components: [ + {name: "left", components: [ + {kind: "List", classes: "enyo-fit", touch: true, count: 1000, onSetupItem: "setupItem", item: "item1", components: [ + {name: "item1", classes: "panels-sample-sliding-item"} + ]} + ]}, + {name: "middle", components: [ + {kind: "List", classes: "enyo-fit", touch: true, count: 1000, onSetupItem: "setupItem", item: "item2", components: [ + {name: "item2", classes: "panels-sample-sliding-item"} + ]} + ]}, + {name: "body", fit: true, components: [ + {kind: "Scroller", classes: "enyo-fit", touch: true, components: [ + {classes: "panels-sample-sliding-content", content: "Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old."} + ]} + ]} + ]} + ], + setupItem: function(inSender, inEvent) { + this.$[inSender.item].setContent("This is row number: " + inEvent.index); + }, + checkboxChange: function(inSender) { + this.log(); + this.$.panels.realtimeFit = inSender.getValue(); + } +}); \ No newline at end of file diff --git a/lib/layout/panels/samples/assets/search-input-search.png b/lib/layout/panels/samples/assets/search-input-search.png new file mode 100644 index 0000000000000000000000000000000000000000..36bf1b5161e9d6b22273b681e43c85859c7c8914 GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/lib/layout/panels/samples/assets/spinner-large.gif b/lib/layout/panels/samples/assets/spinner-large.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee786953dafde87dea34cc8449ba0ef1751e25ec GIT binary patch literal 1924 zcmciDSx{3~00!U)H>$=Sx5pEl!}QW!GH+}t+)Ud2NwuM0|7x0ssUL<2w@8* zW&vXWBWnUt0z@ciSrTLkC|X1TrBFl$I|J5srhO?*;zMUDojTKL&%=4SXYRS*|Ia;V zUx42(4<-e)6Z95j8Y?R+TrPKZc6NDrnMfoml}a2Aw|n<)tyY_yoNQk5=Y(BZd%!m& znC^4Pcl%a1%QeO)*x&8xNvD{}r=l?DW0IpWOg8gETmmy{YfSv<1Q7N&0FE%OaxuNb zv?&NMtnUv{-QD$ixML;4i60eHP7tnVWLMVqjO18cg#~_lzHPCAu??vD$VdO|&09-^ zRDN7=-UWS>YvEVZ?7G%+!aMCSxE|RZfkB^0fn3dcLPQ46Jo6Um3VjoHBofZKr(mEQ z7fUFK9p?y5fD|8+NK4DE$*#-GHQ5)N+WGWD;vDpt7E^R zS5@@%>hyj0`(@qydybt+$@n{j$C$B4nYafzqxhku;eqmL{iJ@pccEwg<;?7o*M`-A zBYy=(E0GW%bZ!{(^6QVAT(sKQ1;xpAXzK|c=Hyb|&zsoV?wM@=HfvtZT$lTPSH#Uo zN3<0{%o!Df;i=KW6gkW%q578%$t0_vQUPoNB@utlFXi%SE}k8GCd{6>_bcJ1BcTGR z5m-@qBfdy_ie;a(wb;8JP;E@l3~aJ%Y4*~f8gFgysH+mzbSliifk9G_^KjHz!zfNm z7`xa;8h5xye2#ly=o%`Yxj)@EsasSm^v%z`A$=%O-QZ?raSXu-)M<7-)m?c_onFUi zp5Z#6tje~a*<6bNj-&0@+Dkh^8jkoL{G=OXxTe!41^VwDXFQiV8}Pm1;iGFh_PBXM znUIXkTy7pOzrY#>C&OWdwuoqiT?ic(4+xNn9A|z!9Cgu)CQCrp#JSW1s0x}Qx~l0y znM^JeMM{J=#U&kGrVa;eN}UX6sg;a}_y*D#yOub9{4r63A9>L>$eYm{iTcGZGm*F| zarpff|DHIo!?|PxCF++I6p&+CEE`E1c^hoXQ=lJMgs0)Xf|qJ89=J8R^lPUwqRtLs zpGX6((Ebi`ogatVS;Mu=bvN`-q6?s_c%cV}bNlyDzx3t4*t z+gN)$UgJ=su8&vYZYZiy=0yBu@;+NI>yhYz0wQjiR*R>oFGR)wB+x0yVwuzb2E;KG z67TP~m;jm9uxv^OEfJZ<1K@>hWC?}FLW#*z9~7S_@Q4e`D=AO}*s9X)tcs( z)_3JLgIS%2zreL;Lk?WUh>4}x!EiZNN9}X(cQArt>+w(>WJ0^SNOQBrpjlAQx6I8h zt$xgWaDy2wM8;)6rJ3_Z%+pPOG$SX3Np?tqU3$B`{X^n+RYBwI zL__N=p@-%6&`LeMM79-hgQC)?WEPMtb+{rdG)RaH-(JUMsn+|#E|jg5^N z7#L>GoSBxEcIM2P|Ns9h{^#~{4GDI33~)8lGhk)}N-O?kVdVmvrUPUHDSie97N-v< zGpEh8XczsY!u2sE{E^Cy1w4|E6lN^oxcN{fu20l=q5U$Khm)QnGb{K^KWY1ZGy>f3j8qEXrAYw_(GDG+gX1D$CnAG+*uHwVgs7P2@Wd*gPmVi zx$;F;->GC^&Jj(Xw4h^M^hJ>j<;8ku@>-l0G#iDqwLVk~;LvJxWe}B_q=YbpiGc~> z7|qGvCiYJzENd^WN%_gZlVG%_bJemG9k(!(RuLV?Yk!PxH7`)G$=i9x!O(zHgvl4l zF$@fBK&OBL#^8d^=T%!zF5PhGZ%4Dom2}y2iR;7{3dkQ|xW0f#esO%0l1;1IL&e2w zr97^wTKsWA3K<5tV@y8SZtmIhqgAwM*);X87N?#|3wT~AYdC2qy9TFpPWJGfugKT3 Wq>R~sp}+a@gG7sHw + + + + Menu Test + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/panels/samples/package.js b/lib/layout/panels/samples/package.js new file mode 100644 index 0000000..b129396 --- /dev/null +++ b/lib/layout/panels/samples/package.js @@ -0,0 +1,8 @@ +enyo.depends( + "PanelsSample.css", + "PanelsSample.js", + "PanelsFlickrSample.css", + "PanelsFlickrSample.js", + "PanelsSlidingSample.css", + "PanelsSlidingSample.js" +); \ No newline at end of file diff --git a/lib/layout/panels/source/Panels.css b/lib/layout/panels/source/Panels.css new file mode 100644 index 0000000..2e79349 --- /dev/null +++ b/lib/layout/panels/source/Panels.css @@ -0,0 +1,12 @@ +.enyo-panels { +} + +.enyo-panels-fit-narrow { +} + +@media all and (max-width: 800px) { + .enyo-panels-fit-narrow > * { + min-width: 100%; + max-width: 100%; + } +} \ No newline at end of file diff --git a/lib/layout/panels/source/Panels.js b/lib/layout/panels/source/Panels.js new file mode 100644 index 0000000..376ad4b --- /dev/null +++ b/lib/layout/panels/source/Panels.js @@ -0,0 +1,427 @@ +/** +The _enyo.Panels_ kind is designed to satisfy a variety of common use cases for +application layout. Using _enyo.Panels_, controls may be arranged as (among +other things) a carousel, a set of collapsing panels, a card stack that fades +between panels, or a grid. + +Any Enyo control may be placed inside an _enyo.Panels_, but by convention we +refer to each of these controls as a "panel." From the set of panels in an +_enyo.Panels_, one is considered to be active. The active panel is set by index +using the _setIndex_ method. The actual layout of the panels typically changes +each time the active panel is set, such that the new active panel has the most +prominent position. + +For more information, see the +[Panels documentation](https://github.com/enyojs/enyo/wiki/Panels) in the Enyo +Developer Guide. +*/ +enyo.kind({ + name: "enyo.Panels", + classes: "enyo-panels", + published: { + /** + The index of the active panel. The layout of panels is controlled by + the layoutKind, but as a rule, the active panel is displayed in the + most prominent position. For example, in the (default) CardArranger + layout, the active panel is shown and the other panels are hidden. + */ + index: 0, + //* Controls whether the user can drag between panels. + draggable: true, + //* Controls whether the panels animate when transitioning; for example, + //* when _setIndex_ is called. + animate: true, + //* Controls whether panels "wrap around" when moving past the end. + //* The actual effect depends upon the arranger in use. + wrap: false, + //* Sets the arranger kind to be used for dynamic layout. + arrangerKind: "CardArranger", + //* By default, each panel will be sized to fit the Panels' width when + //* the screen size is narrow enough (less than 800px). Set to false + //* to avoid this behavior. + narrowFit: true + }, + events: { + /** + Fires at the start of a panel transition, when _setIndex_ is called + and also during dragging. + + _inEvent.fromIndex_ contains the index of the old panel. + + _inEvent.toIndex_ contains the index of the new panel. + */ + onTransitionStart: "", + /** + Fires at the end of a panel transition, when _setIndex_ is called + and also during dragging. + + _inEvent.fromIndex_ contains the index of the old panel. + + _inEvent.toIndex_ contains the index of the new panel. + */ + onTransitionFinish: "" + }, + //* @protected + handlers: { + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish", + onscroll: "domScroll" + }, + tools: [ + {kind: "Animator", onStep: "step", onEnd: "completed"} + ], + fraction: 0, + create: function() { + this.transitionPoints = []; + this.inherited(arguments); + this.arrangerKindChanged(); + this.narrowFitChanged(); + this.indexChanged(); + }, + rendered: function() { + this.inherited(arguments); + enyo.makeBubble(this, "scroll"); + }, + domScroll: function(inSender, inEvent) { + if (this.hasNode()) { + if (this.node.scrollLeft > 0) { + // Reset scrollLeft position + this.node.scrollLeft = 0; + } + } + }, + initComponents: function() { + this.createChrome(this.tools); + this.inherited(arguments); + }, + arrangerKindChanged: function() { + this.setLayoutKind(this.arrangerKind); + }, + narrowFitChanged: function() { + this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); + }, + destroy: function() { + // When the entire panels is going away, take note so we don't try and do single-panel + // remove logic such as changing the index and reflowing when each panel is destroyed + this.destroying = true; + this.inherited(arguments); + }, + removeControl: function(inControl) { + this.inherited(arguments); + if (this.destroying && this.controls.length > 0 && this.isPanel(inControl)) { + this.setIndex(Math.max(this.index - 1, 0)); + this.flow(); + this.reflow(); + } + }, + isPanel: function() { + // designed to be overridden in kinds derived from Panels that have + // non-panel client controls + return true; + }, + flow: function() { + this.arrangements = []; + this.inherited(arguments); + }, + reflow: function() { + this.arrangements = []; + this.inherited(arguments); + this.refresh(); + }, + //* @public + /** + Returns an array of contained panels. + Subclasses can override this if they don't want the arranger to layout all of their children + */ + getPanels: function() { + var p = this.controlParent || this; + return p.children; + }, + //* Returns a reference to the active panel--i.e., the panel at the specified index. + getActive: function() { + var p$ = this.getPanels(); + //Constrain the index within the array of panels, needed if wrapping is enabled + var index = this.index % p$.length; + if (index < 0) { + index += p$.length; + } + return p$[index]; + }, + /** + Returns a reference to the enyo.Animator + instance used to animate panel transitions. The Panels' animator can be used + to set the duration of panel transitions, e.g.: + + this.getAnimator().setDuration(1000); + */ + getAnimator: function() { + return this.$.animator; + }, + /** + Sets the active panel to the panel specified by the given index. + Note that if the _animate_ property is set to true, the active panel + will animate into view. + */ + setIndex: function(inIndex) { + // override setIndex so that indexChanged is called + // whether this.index has actually changed or not + this.setPropertyValue("index", inIndex, "indexChanged"); + }, + /** + Sets the active panel to the panel specified by the given index. + Regardless of the value of the _animate_ property, the transition to the + next panel will not animate and will be immediate. + */ + setIndexDirect: function(inIndex) { + this.setIndex(inIndex); + this.completed(); + }, + //* Transitions to the previous panel--i.e., the panel whose index value is + //* one less than that of the current active panel. + previous: function() { + this.setIndex(this.index-1); + }, + //* Transitions to the next panel--i.e., the panel whose index value is one + //* greater than that of the current active panel. + next: function() { + this.setIndex(this.index+1); + }, + //* @protected + clamp: function(inValue) { + var l = this.getPanels().length-1; + if (this.wrap) { + // FIXME: dragging makes assumptions about direction and from->start indexes. + //return inValue < 0 ? l : (inValue > l ? 0 : inValue); + return inValue; + } else { + return Math.max(0, Math.min(inValue, l)); + } + }, + indexChanged: function(inOld) { + this.lastIndex = inOld; + this.index = this.clamp(this.index); + if (!this.dragging && this.$.animator) { + if (this.$.animator.isAnimating()) { + this.completed(); + } + this.$.animator.stop(); + if (this.hasNode()) { + if (this.animate) { + this.startTransition(); + this.$.animator.play({ + startValue: this.fraction + }); + } else { + this.refresh(); + } + } + } + }, + step: function(inSender) { + this.fraction = inSender.value; + this.stepTransition(); + }, + completed: function() { + if (this.$.animator.isAnimating()) { + this.$.animator.stop(); + } + this.fraction = 1; + this.stepTransition(); + this.finishTransition(); + }, + dragstart: function(inSender, inEvent) { + if (this.draggable && this.layout && this.layout.canDragEvent(inEvent)) { + inEvent.preventDefault(); + this.dragstartTransition(inEvent); + this.dragging = true; + this.$.animator.stop(); + return true; + } + }, + drag: function(inSender, inEvent) { + if (this.dragging) { + inEvent.preventDefault(); + this.dragTransition(inEvent); + } + }, + dragfinish: function(inSender, inEvent) { + if (this.dragging) { + this.dragging = false; + inEvent.preventTap(); + this.dragfinishTransition(inEvent); + } + }, + dragstartTransition: function(inEvent) { + if (!this.$.animator.isAnimating()) { + var f = this.fromIndex = this.index; + this.toIndex = f - (this.layout ? this.layout.calcDragDirection(inEvent) : 0); + } else { + this.verifyDragTransition(inEvent); + } + this.fromIndex = this.clamp(this.fromIndex); + this.toIndex = this.clamp(this.toIndex); + //this.log(this.fromIndex, this.toIndex); + this.fireTransitionStart(); + if (this.layout) { + this.layout.start(); + } + }, + dragTransition: function(inEvent) { + // note: for simplicity we choose to calculate the distance directly between + // the first and last transition point. + var d = this.layout ? this.layout.calcDrag(inEvent) : 0; + var t$ = this.transitionPoints, s = t$[0], f = t$[t$.length-1]; + var as = this.fetchArrangement(s); + var af = this.fetchArrangement(f); + var dx = this.layout ? this.layout.drag(d, s, as, f, af) : 0; + var dragFail = d && !dx; + if (dragFail) { + //this.log(dx, s, as, f, af); + } + this.fraction += dx; + var fr = this.fraction; + if (fr > 1 || fr < 0 || dragFail) { + if (fr > 0 || dragFail) { + this.dragfinishTransition(inEvent); + } + this.dragstartTransition(inEvent); + this.fraction = 0; + // FIXME: account for lost fraction + //this.dragTransition(inEvent); + } + this.stepTransition(); + }, + dragfinishTransition: function(inEvent) { + this.verifyDragTransition(inEvent); + this.setIndex(this.toIndex); + // note: if we're still dragging, then we're at a transition boundary + // and should fire the finish event + if (this.dragging) { + this.fireTransitionFinish(); + } + }, + verifyDragTransition: function(inEvent) { + var d = this.layout ? this.layout.calcDragDirection(inEvent) : 0; + var f = Math.min(this.fromIndex, this.toIndex); + var t = Math.max(this.fromIndex, this.toIndex); + if (d > 0) { + var s = f; + f = t; + t = s; + } + if (f != this.fromIndex) { + this.fraction = 1 - this.fraction; + } + //this.log("old", this.fromIndex, this.toIndex, "new", f, t); + this.fromIndex = f; + this.toIndex = t; + }, + refresh: function() { + if (this.$.animator && this.$.animator.isAnimating()) { + this.$.animator.stop(); + } + this.startTransition(); + this.fraction = 1; + this.stepTransition(); + this.finishTransition(); + }, + startTransition: function() { + this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0; + this.toIndex = this.toIndex != null ? this.toIndex : this.index; + //this.log(this.id, this.fromIndex, this.toIndex); + if (this.layout) { + this.layout.start(); + } + this.fireTransitionStart(); + }, + finishTransition: function() { + if (this.layout) { + this.layout.finish(); + } + this.transitionPoints = []; + this.fraction = 0; + this.fromIndex = this.toIndex = null; + this.fireTransitionFinish(); + }, + fireTransitionStart: function() { + var t = this.startTransitionInfo; + if (this.hasNode() && (!t || (t.fromIndex != this.fromIndex || t.toIndex != this.toIndex))) { + this.startTransitionInfo = {fromIndex: this.fromIndex, toIndex: this.toIndex}; + this.doTransitionStart(enyo.clone(this.startTransitionInfo)); + } + }, + fireTransitionFinish: function() { + var t = this.finishTransitionInfo; + if (this.hasNode() && (!t || (t.fromIndex != this.lastIndex || t.toIndex != this.index))) { + this.finishTransitionInfo = {fromIndex: this.lastIndex, toIndex: this.index}; + this.doTransitionFinish(enyo.clone(this.finishTransitionInfo)); + } + this.lastIndex=this.index; + }, + // gambit: we interpolate between arrangements as needed. + stepTransition: function() { + if (this.hasNode()) { + // select correct transition points and normalize fraction. + var t$ = this.transitionPoints; + var r = (this.fraction || 0) * (t$.length-1); + var i = Math.floor(r); + r = r - i; + var s = t$[i], f = t$[i+1]; + // get arrangements and lerp between them + var s0 = this.fetchArrangement(s); + var s1 = this.fetchArrangement(f); + this.arrangement = s0 && s1 ? enyo.Panels.lerp(s0, s1, r) : (s0 || s1); + if (this.arrangement && this.layout) { + this.layout.flowArrangement(); + } + } + }, + fetchArrangement: function(inName) { + if ((inName != null) && !this.arrangements[inName] && this.layout) { + this.layout._arrange(inName); + this.arrangements[inName] = this.readArrangement(this.getPanels()); + } + return this.arrangements[inName]; + }, + readArrangement: function(inC) { + var r = []; + for (var i=0, c$=inC, c; (c=c$[i]); i++) { + r.push(enyo.clone(c._arranger)); + } + return r; + }, + statics: { + //* @public + /** + Returns true when window width is 800px or less. This value must be + the same as the "max-width" media query used for panel sizing in + _Panels.css_. + */ + isScreenNarrow: function() { + return enyo.dom.getWindowWidth() <= 800; + }, + //* @protected + lerp: function(inA0, inA1, inFrac) { + var r = []; + for (var i=0, k$=enyo.keys(inA0), k; (k=k$[i]); i++) { + r.push(this.lerpObject(inA0[k], inA1[k], inFrac)); + } + return r; + }, + lerpObject: function(inNew, inOld, inFrac) { + var b = enyo.clone(inNew), n, o; + // inOld might be undefined when deleting panels + if (inOld) { + for (var i in inNew) { + n = inNew[i]; + o = inOld[i]; + if (n != o) { + b[i] = n - (n - o) * inFrac; + } + } + } + return b; + } + } +}); \ No newline at end of file diff --git a/lib/layout/panels/source/arrangers/Arranger.css b/lib/layout/panels/source/arrangers/Arranger.css new file mode 100644 index 0000000..9135a32 --- /dev/null +++ b/lib/layout/panels/source/arrangers/Arranger.css @@ -0,0 +1,25 @@ +.enyo-arranger { + position: relative; + overflow: hidden; +} + +.enyo-arranger.enyo-fit { + position: absolute; +} + +.enyo-arranger > * { + position: absolute; + left: 0; + top: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.enyo-arranger-fit > * { + /* override any width/height set on panels */ + width: 100% !important; + height: 100% !important; + min-width: 0 !important; + min-height: 0 !important; +} diff --git a/lib/layout/panels/source/arrangers/Arranger.js b/lib/layout/panels/source/arrangers/Arranger.js new file mode 100644 index 0000000..2fab3dd --- /dev/null +++ b/lib/layout/panels/source/arrangers/Arranger.js @@ -0,0 +1,230 @@ +/** + _enyo.Arranger_ is an enyo.Layout that considers + one of the controls it lays out as active. The other controls are placed + relative to the active control as makes sense for the layout. + + Arranger supports dynamic layouts, meaning it's possible to transition + between its layouts via animation. Typically, arrangers should lay out + controls using CSS transforms, since these are optimized for animation. To + support this, the controls in an Arranger are absolutely positioned, and + the Arranger kind has an `accelerated` property, which marks controls for + CSS compositing. The default setting of "auto" ensures that this will occur + if enabled by the platform. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "enyo.Arranger", + kind: "Layout", + layoutClass: "enyo-arranger", + /** + Sets controls being laid out to use CSS compositing. A setting of "auto" + will mark controls for compositing if the platform supports it. + */ + accelerated: "auto", + //* Property of the drag event used to calculate the amount a drag moves the layout + dragProp: "ddx", + //* Property of the drag event used to calculate the direction of a drag + dragDirectionProp: "xDirection", + //* Property of the drag event used to calculate whether a drag should occur + canDragProp: "horizontal", + /** + If set to true, transitions between non-adjacent arrangements will go + through the intermediate arrangements. This is useful when direct + transitions between arrangements would be visually jarring. + */ + incrementalPoints: false, + /** + Called when removing an arranger (for example, when switching a Panels + control to a different arrangerKind). Subclasses should implement this + function to reset whatever properties they've changed on child controls. + You *must* call the superclass implementation in your subclass's + _destroy_ function. + */ + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + c._arranger = null; + } + this.inherited(arguments); + }, + /** + Arranges the given array of controls (_inC_) in the layout specified by + _inName_. When implementing this method, rather than apply styling + directly to controls, call _arrangeControl(inControl, inArrangement)_ + with an _inArrangement_ object with styling settings. These will then be + applied via the _flowControl(inControl, inArrangement)_ method. + */ + arrange: function(inC, inName) { + }, + /** + Sizes the controls in the layout. This method is called only at reflow + time. Note that sizing is separated from other layout done in the + _arrange_ method because it is expensive and not suitable for dynamic + layout. + */ + size: function() { + }, + /** + Called when a layout transition begins. Implement this method to perform + tasks that should only occur when a transition starts; for example, some + controls could be shown or hidden. In addition, the _transitionPoints_ + array may be set on the container to dictate the named arrangments + between which the transition occurs. + */ + start: function() { + var f = this.container.fromIndex, t = this.container.toIndex; + var p$ = this.container.transitionPoints = [f]; + // optionally add a transition point for each index between from and to. + if (this.incrementalPoints) { + var d = Math.abs(t - f) - 2; + var i = f; + while (d >= 0) { + i = i + (t < f ? -1 : 1); + p$.push(i); + d--; + } + } + p$.push(this.container.toIndex); + }, + /** + Called when a layout transition completes. Implement this method to + perform tasks that should only occur when a transition ends; for + example, some controls could be shown or hidden. + */ + finish: function() { + }, + /** + Called when dragging the layout, this method returns the difference in + pixels between the arrangement _inA0_ for layout setting _inI0_ and + arrangement _inA1_ for layout setting _inI1_. This data is used to calculate + the percentage that a drag should move the layout between two active states. + */ + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + }, + //* @protected + canDragEvent: function(inEvent) { + return inEvent[this.canDragProp]; + }, + calcDragDirection: function(inEvent) { + return inEvent[this.dragDirectionProp]; + }, + calcDrag: function(inEvent) { + return inEvent[this.dragProp]; + }, + drag: function(inDp, inAn, inA, inBn, inB) { + var f = this.measureArrangementDelta(-inDp, inAn, inA, inBn, inB); + return f; + }, + measureArrangementDelta: function(inX, inI0, inA0, inI1, inA1) { + var d = this.calcArrangementDifference(inI0, inA0, inI1, inA1); + var s = d ? inX / Math.abs(d) : 0; + s = s * (this.container.fromIndex > this.container.toIndex ? -1 : 1); + //enyo.log("delta", s); + return s; + }, + _arrange: function(inIndex) { + // guard against being called before we've been rendered + if (!this.containerBounds) { + this.reflow(); + } + var c$ = this.getOrderedControls(inIndex); + this.arrange(c$, inIndex); + }, + arrangeControl: function(inControl, inArrangement) { + inControl._arranger = enyo.mixin(inControl._arranger || {}, inArrangement); + }, + // called before HTML is generated + flow: function() { + this.c$ = [].concat(this.container.getPanels()); + this.controlsIndex = 0; + for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { + enyo.dom.accelerate(c, this.accelerated); + if (enyo.platform.safari) { + // On Safari-desktop, sometimes having the panel's direct child set to accelerate isn't sufficient + // this is most often the case with Lists contained inside another control, inside a Panels + var grands=c.children; + for (var j=0, kid; (kid=grands[j]); j++) { + enyo.dom.accelerate(kid, this.accelerated); + } + } + } + }, + // called during "rendered" phase + reflow: function() { + var cn = this.container.hasNode(); + this.containerBounds = cn ? {width: cn.clientWidth, height: cn.clientHeight} : {}; + this.size(); + }, + flowArrangement: function() { + var a = this.container.arrangement; + if (a) { + for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { + this.flowControl(c, a[i]); + } + } + }, + //* @public + /** + Lays out the control (_inControl_) according to the settings stored in + the _inArrangment_ object. By default, _flowControl_ will apply settings + of left, top, and opacity. This method should only be implemented to + apply other settings made via _arrangeControl_. + */ + flowControl: function(inControl, inArrangement) { + enyo.Arranger.positionControl(inControl, inArrangement); + var o = inArrangement.opacity; + if (o != null) { + enyo.Arranger.opacifyControl(inControl, o); + } + }, + //* @protected + // Gets an array of controls arranged in state order. + // note: optimization, dial around a single array. + getOrderedControls: function(inIndex) { + var whole = Math.floor(inIndex); + var a = whole - this.controlsIndex; + var sign = a > 0; + var c$ = this.c$ || []; + for (var i=0; i 0.99 ? 1 : (o < 0.01 ? 0 : o); + // note: we only care about ie8 + if (enyo.platform.ie < 9) { + inControl.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (o * 100) + ")"); + } else { + inControl.applyStyle("opacity", o); + } + } + } +}); diff --git a/lib/layout/panels/source/arrangers/CardArranger.js b/lib/layout/panels/source/arrangers/CardArranger.js new file mode 100644 index 0000000..81e882a --- /dev/null +++ b/lib/layout/panels/source/arrangers/CardArranger.js @@ -0,0 +1,53 @@ +/** + _enyo.CardArranger_ is an enyo.Arranger that + displays only one active control. The non-active controls are hidden with + _setShowing(false)_. Transitions between arrangements are handled by fading + from one control to the next. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.CardArranger", + kind: "Arranger", + //* @protected + layoutClass: "enyo-arranger enyo-arranger-fit", + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + return this.containerBounds.width; + }, + arrange: function(inC, inName) { + for (var i=0, c, b, v; (c=inC[i]); i++) { + v = (i === 0) ? 1 : 0; + this.arrangeControl(c, {opacity: v}); + } + }, + start: function() { + this.inherited(arguments); + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + var wasShowing=c.showing; + c.setShowing(i == this.container.fromIndex || i == (this.container.toIndex)); + if (c.showing && !wasShowing) { + c.resized(); + } + } + }, + finish: function() { + this.inherited(arguments); + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + c.setShowing(i == this.container.toIndex); + } + }, + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + enyo.Arranger.opacifyControl(c, 1); + if (!c.showing) { + c.setShowing(true); + } + } + this.inherited(arguments); + } +}); diff --git a/lib/layout/panels/source/arrangers/CardSlideInArranger.js b/lib/layout/panels/source/arrangers/CardSlideInArranger.js new file mode 100644 index 0000000..83c45d0 --- /dev/null +++ b/lib/layout/panels/source/arrangers/CardSlideInArranger.js @@ -0,0 +1,67 @@ +/** + _enyo.CardSlideInArranger_ is an enyo.Arranger + that displays only one active control. The non-active controls are hidden + with _setShowing(false)_. Transitions between arrangements are handled by + sliding the new control over the current one. + + Note that CardSlideInArranger always slides controls in from the right. If + you want an arranger that slides to the right and left, try + enyo.LeftRightArranger. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.CardSlideInArranger", + kind: "CardArranger", + //* @protected + start: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + var wasShowing=c.showing; + c.setShowing(i == this.container.fromIndex || i == (this.container.toIndex)); + if (c.showing && !wasShowing) { + c.resized(); + } + } + var l = this.container.fromIndex; + i = this.container.toIndex; + this.container.transitionPoints = [ + i + "." + l + ".s", + i + "." + l + ".f" + ]; + }, + finish: function() { + this.inherited(arguments); + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + c.setShowing(i == this.container.toIndex); + } + }, + arrange: function(inC, inName) { + var p = inName.split("."); + var f = p[0], s= p[1], starting = (p[2] == "s"); + var b = this.containerBounds.width; + for (var i=0, c$=this.container.getPanels(), c, v; (c=c$[i]); i++) { + v = b; + if (s == i) { + v = starting ? 0 : -b; + } + if (f == i) { + v = starting ? b : 0; + } + if (s == i && s == f) { + v = 0; + } + this.arrangeControl(c, {left: v}); + } + }, + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + enyo.Arranger.positionControl(c, {left: null}); + } + this.inherited(arguments); + } +}); diff --git a/lib/layout/panels/source/arrangers/CarouselArranger.js b/lib/layout/panels/source/arrangers/CarouselArranger.js new file mode 100644 index 0000000..253000b --- /dev/null +++ b/lib/layout/panels/source/arrangers/CarouselArranger.js @@ -0,0 +1,117 @@ +/** + _enyo.CarouselArranger_ is an enyo.Arranger + that displays the active control, along with some number of inactive + controls to fill the available space. The active control is positioned on + the left side of the container, and the rest of the views are laid out to + the right. + + One of the controls may have _fit: true_ set, in which case it will take up + any remaining space after all of the other controls have been sized. + + For best results with CarouselArranger, you should set a minimum width for + each control via a CSS style, e.g., _min-width: 25%_ or _min-width: 250px_. + + Transitions between arrangements are handled by sliding the new controls in + from the right and sliding the old controls off to the left. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.CarouselArranger", + kind: "Arranger", + //* @protected + size: function() { + var c$ = this.container.getPanels(); + var padding = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}; + var pb = this.containerBounds; + var i, e, s, m, c; + pb.height -= padding.top + padding.bottom; + pb.width -= padding.left + padding.right; + // used space + var fit; + for (i=0, s=0; (c=c$[i]); i++) { + m = enyo.dom.calcMarginExtents(c.hasNode()); + c.width = c.getBounds().width; + c.marginWidth = m.right + m.left; + s += (c.fit ? 0 : c.width) + c.marginWidth; + if (c.fit) { + fit = c; + } + } + if (fit) { + var w = pb.width - s; + fit.width = w >= 0 ? w : fit.width; + } + for (i=0, e=padding.left; (c=c$[i]); i++) { + c.setBounds({top: padding.top, bottom: padding.bottom, width: c.fit ? c.width : null}); + } + }, + arrange: function(inC, inName) { + if (this.container.wrap) { + this.arrangeWrap(inC, inName); + } else { + this.arrangeNoWrap(inC, inName); + } + }, + arrangeNoWrap: function(inC, inName) { + var i, aw, cw, c; + var c$ = this.container.getPanels(); + var s = this.container.clamp(inName); + var nw = this.containerBounds.width; + // do we have enough content to fill the width? + for (i=s, cw=0; (c=c$[i]); i++) { + cw += c.width + c.marginWidth; + if (cw > nw) { + break; + } + } + // if content width is less than needed, adjust starting point index and offset + var n = nw - cw; + var o = 0; + if (n > 0) { + var s1 = s; + for (i=s-1, aw=0; (c=c$[i]); i--) { + aw += c.width + c.marginWidth; + if (n - aw <= 0) { + o = (n - aw); + s = i; + break; + } + } + } + // arrange starting from needed index with detected offset so we fill space + var w, e; + for (i=0, e=this.containerPadding.left + o; (c=c$[i]); i++) { + w = c.width + c.marginWidth; + if (i < s) { + this.arrangeControl(c, {left: -w}); + } else { + this.arrangeControl(c, {left: Math.floor(e)}); + e += w; + } + } + }, + arrangeWrap: function(inC, inName) { + for (var i=0, e=this.containerPadding.left, m, c; (c=inC[i]); i++) { + this.arrangeControl(c, {left: e}); + e += c.width + c.marginWidth; + } + }, + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + var i = Math.abs(inI0 % this.c$.length); + return inA0[i].left - inA1[i].left; + }, + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + enyo.Arranger.positionControl(c, {left: null, top: null}); + c.applyStyle("top", null); + c.applyStyle("bottom", null); + c.applyStyle("left", null); + c.applyStyle("width", null); + } + this.inherited(arguments); + } +}); diff --git a/lib/layout/panels/source/arrangers/CollapsingArranger.js b/lib/layout/panels/source/arrangers/CollapsingArranger.js new file mode 100644 index 0000000..1ca6cd3 --- /dev/null +++ b/lib/layout/panels/source/arrangers/CollapsingArranger.js @@ -0,0 +1,101 @@ +/** + _enyo.CollapsingArranger_ is an enyo.Arranger + that displays the active control, along with some number of inactive + controls to fill the available space. The active control is positioned on + the left side of the container and the rest of the views are laid out to the + right. The last control, if visible, will expand to fill whatever space is + not taken up by the previous controls. + + For best results with CollapsingArranger, you should set a minimum width + for each control via a CSS style, e.g., _min-width: 25%_ or + _min-width: 250px_. + + Transitions between arrangements are handled by sliding the new control in + from the right and collapsing the old control to the left. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.CollapsingArranger", + kind: "CarouselArranger", + /** + The "peekWidth" property specifies the amount each panel should be + offset from the left when it is selected. This allows controls on the + underlying panel to the left of the selected one to be partially + revealed. + */ + peekWidth: 0, + //* @protected + size: function() { + this.clearLastSize(); + this.inherited(arguments); + }, + // clear size from last if it's not actually the last + // (required for adding another control) + clearLastSize: function() { + for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { + if (c._fit && i != c$.length-1) { + c.applyStyle("width", null); + c._fit = null; + } + } + }, + constructor: function() { + this.inherited(arguments); + this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; + }, + arrange: function(inC, inIndex) { + var c$ = this.container.getPanels(); + for (var i=0, e=this.containerPadding.left, m, c, n=0; (c=c$[i]); i++) { + if(c.getShowing()){ + this.arrangeControl(c, {left: e + n * this.peekWidth}); + if (i >= inIndex) { + e += c.width + c.marginWidth - this.peekWidth; + } + n++; + } else { + this.arrangeControl(c, {left: e}); + if (i >= inIndex) { + e += c.width + c.marginWidth; + } + } + // FIXME: overdragging-ish + if (i == c$.length - 1 && inIndex < 0) { + this.arrangeControl(c, {left: e - inIndex}); + } + } + }, + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + var i = this.container.getPanels().length-1; + return Math.abs(inA1[i].left - inA0[i].left); + }, + flowControl: function(inControl, inA) { + this.inherited(arguments); + if (this.container.realtimeFit) { + var c$ = this.container.getPanels(); + var l = c$.length-1; + var last = c$[l]; + if (inControl == last) { + this.fitControl(inControl, inA.left); + } + } + + }, + finish: function() { + this.inherited(arguments); + if (!this.container.realtimeFit && this.containerBounds) { + var c$ = this.container.getPanels(); + var a$ = this.container.arrangement; + var l = c$.length-1; + var c = c$[l]; + this.fitControl(c, a$[l].left); + } + }, + fitControl: function(inControl, inOffset) { + inControl._fit = true; + inControl.applyStyle("width", (this.containerBounds.width - inOffset) + "px"); + inControl.resized(); + } +}); diff --git a/lib/layout/panels/source/arrangers/DockRightArranger.js b/lib/layout/panels/source/arrangers/DockRightArranger.js new file mode 100644 index 0000000..47eab1a --- /dev/null +++ b/lib/layout/panels/source/arrangers/DockRightArranger.js @@ -0,0 +1,133 @@ +/** + _enyo.DockRightArranger_ is an enyo.Arranger + that displays the active control, along with some number of inactive + controls to fill the available space. The active control is positioned on + the right side of the container and the rest of the views are laid out to the + right. + + For best results with DockRightArranger, you should set a minimum width + for each control via a CSS style, e.g., _min-width: 25%_ or + _min-width: 250px_. + + Transitions between arrangements are handled by sliding the new control in + from the right. If the width of the old control(s) can fit within the container, + they will slide to the left. If not, the old control(s) will collapse to the left. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.DockRightArranger", + kind: "Arranger", + //* If true, the base panel (index 0) will fill the width of the container, + //* while newer controls will slide in and collapse on top of it + basePanel: false, + //* How many px should panels overlap + overlap: 0, + //* Column width + layoutWidth: 0, + //* @protected + constructor: function() { + this.inherited(arguments); + this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap; + this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; + }, + size: function() { + var c$ = this.container.getPanels(); + var padding = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}; + var pb = this.containerBounds; + var i, m, c; + pb.width -= padding.left + padding.right; + var nw = pb.width; + var len = c$.length; + // panel arrangement positions + this.container.transitionPositions = {}; + + for (i=0; (c=c$[i]); i++) { + c.width = ((i===0) && (this.container.basePanel)) ? nw : c.getBounds().width; + } + + for (i=0; (c=c$[i]); i++) { + + if ((i===0) && (this.container.basePanel)) { + c.setBounds({width: nw}); + } + c.setBounds({top: padding.top, bottom: padding.bottom}); + + for (j=0; (c=c$[j]); j++) { + var xPos; + // index 0 always should always be left-aligned at 0px + if ((i===0) && (this.container.basePanel)) { + xPos = 0; + // else newer panels should be positioned off the viewport + } else if (j < i) { + xPos = nw; + // else active panel should be right-aligned + } else if (i === j) { + var offset = nw > this.layoutWidth ? this.overlap : 0; + xPos = (nw - c$[i].width) + offset; + } else { + break; + } + this.container.transitionPositions[i + "." + j] = xPos; + } + + if (j < len) { + var leftAlign = false; + for (k=i+1; k nw ) { + //} else if ( (c$[i].width + c$[k].width) > nw ) { + offset = 0; + leftAlign = true; + } else { + offset = c$[i].width - this.overlap; + for (m=i; menyo.Arranger + that displays the active control and some of the previous and next controls. + The active control is centered horizontally in the container, and the + previous and next controls are laid out to the left and right, respectively. + + Transitions between arrangements are handled by sliding the new control + in from the right and sliding the active control out to the left. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.LeftRightArranger", + kind: "Arranger", + //* The margin width (i.e., how much of the previous and next controls + //* are visible) in pixels + margin: 40, + //* @protected + axisSize: "width", + offAxisSize: "height", + axisPosition: "left", + constructor: function() { + this.inherited(arguments); + this.margin = this.container.margin != null ? this.container.margin : this.margin; + }, + size: function() { + var c$ = this.container.getPanels(); + var port = this.containerBounds[this.axisSize]; + var box = port - this.margin -this.margin; + for (var i=0, b, c; (c=c$[i]); i++) { + b = {}; + b[this.axisSize] = box; + b[this.offAxisSize] = "100%"; + c.setBounds(b); + } + }, + start: function() { + this.inherited(arguments); + + var s = this.container.fromIndex; + var f = this.container.toIndex; + var c$ = this.getOrderedControls(f); + var o = Math.floor(c$.length/2); + + for (var i=0, c; (c=c$[i]); i++) { + if (s > f){ + if (i == (c$.length - o)){ + c.applyStyle("z-index", 0); + } else { + c.applyStyle("z-index", 1); + } + } else { + if (i == (c$.length-1 - o)){ + c.applyStyle("z-index", 0); + } else { + c.applyStyle("z-index", 1); + } + } + } + }, + arrange: function(inC, inIndex) { + var i,c,v,b; + if (this.container.getPanels().length==1){ + b = {}; + b[this.axisPosition] = this.margin; + this.arrangeControl(this.container.getPanels()[0], b); + return; + } + var o = Math.floor(this.container.getPanels().length/2); + var c$ = this.getOrderedControls(Math.floor(inIndex)-o); + var box = this.containerBounds[this.axisSize] - this.margin -this.margin; + var e = this.margin - box * o; + for (i=0; (c=c$[i]); i++) { + b = {}; + b[this.axisPosition] = e; + this.arrangeControl(c, b); + e += box; + } + }, + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + if (this.container.getPanels().length==1){ + return 0; + } + + var i = Math.abs(inI0 % this.c$.length); + //enyo.log(inI0, inI1); + return inA0[i][this.axisPosition] - inA1[i][this.axisPosition]; + }, + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + enyo.Arranger.positionControl(c, {left: null, top: null}); + enyo.Arranger.opacifyControl(c, 1); + c.applyStyle("left", null); + c.applyStyle("top", null); + c.applyStyle("height", null); + c.applyStyle("width", null); + } + this.inherited(arguments); + } +}); + +//* @public +/** + _enyo.TopBottomArranger_ is an enyo.Arranger + that displays the active control and some of the previous and next controls. + The active control is centered vertically in the container, and the previous + and next controls are laid out above and below, respectively. + + Transitions between arrangements are handled by sliding the new control + in from the bottom and sliding the active control out the top. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.TopBottomArranger", + kind: "LeftRightArranger", + //* Property of the drag event used to calculate the amount a drag moves + //* the layout + dragProp: "ddy", + //* Property of the drag event used to calculate the direction of a drag + dragDirectionProp: "yDirection", + //* Property of the drag event used to calculate whether a drag should occur + canDragProp: "vertical", + //* @protected + axisSize: "height", + offAxisSize: "width", + axisPosition: "top" +}); + +//* @public +/** + _enyo.SpiralArranger_ is an enyo.Arranger that + arranges controls in a spiral. The active control is positioned on top and + the other controls are laid out in a spiral pattern below. + + Transitions between arrangements are handled by rotating the new control + up from below and rotating the active control down to the end of the spiral. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.SpiralArranger", + kind: "Arranger", + //* Always go through incremental arrangements when transitioning + incrementalPoints: true, + //* The amount of space between successive controls + inc: 20, + //* @protected + size: function() { + var c$ = this.container.getPanels(); + var b = this.containerBounds; + var w = this.controlWidth = b.width/3; + var h = this.controlHeight = b.height/3; + for (var i=0, c; (c=c$[i]); i++) { + c.setBounds({width: w, height: h}); + } + }, + arrange: function(inC, inName) { + var s = this.inc; + for (var i=0, l=inC.length, c; (c=inC[i]); i++) { + var x = Math.cos(i/l * 2*Math.PI) * i * s + this.controlWidth; + var y = Math.sin(i/l * 2*Math.PI) * i * s + this.controlHeight; + this.arrangeControl(c, {left: x, top: y}); + } + }, + start: function() { + this.inherited(arguments); + var c$ = this.getOrderedControls(this.container.toIndex); + for (var i=0, c; (c=c$[i]); i++) { + c.applyStyle("z-index", c$.length - i); + } + }, + calcArrangementDifference: function(inI0, inA0, inI1, inA1) { + return this.controlWidth; + }, + destroy: function() { + var c$ = this.container.getPanels(); + for (var i=0, c; (c=c$[i]); i++) { + c.applyStyle("z-index", null); + enyo.Arranger.positionControl(c, {left: null, top: null}); + c.applyStyle("left", null); + c.applyStyle("top", null); + c.applyStyle("height", null); + c.applyStyle("width", null); + } + this.inherited(arguments); + } +}); + +//* @public +/** + _enyo.GridArranger_ is an enyo.Arranger that + arranges controls in a grid. The active control is positioned at the + top-left of the grid and the other controls are laid out from left to right + and then from top to bottom. + + Transitions between arrangements are handled by moving the active control to + the end of the grid and shifting the other controls to the left, or up to + the previous row, to fill the space. + + For more information, see the documentation on + [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "enyo.GridArranger", + kind: "Arranger", + //* Always go through incremental arrangements when transitioning + incrementalPoints: true, + //* @public + //* Column width + colWidth: 100, + //* Column height + colHeight: 100, + //* @protected + size: function() { + var c$ = this.container.getPanels(); + var w=this.colWidth, h=this.colHeight; + for (var i=0, c; (c=c$[i]); i++) { + c.setBounds({width: w, height: h}); + } + }, + arrange: function(inC, inIndex) { + var w=this.colWidth, h=this.colHeight; + var cols = Math.max(1, Math.floor(this.containerBounds.width / w)); + var c; + for (var y=0, i=0; i + + + + Slideable Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/slideable/samples/SlideableSample.js b/lib/layout/slideable/samples/SlideableSample.js new file mode 100644 index 0000000..a125795 --- /dev/null +++ b/lib/layout/slideable/samples/SlideableSample.js @@ -0,0 +1,98 @@ +enyo.kind({ + name: "enyo.sample.SlideableSample", + classes: "enyo-unselectable enyo-fit", + style: "overflow: hidden; background-color: #000;", + components: [ + {name: "top", kind: "Slideable", axis: "v", unit: "%", min: -90, max: 0, classes: "enyo-fit slideable-sample top", onChange: "updateInfo"}, + {name: "right", kind: "Slideable", axis: "h", unit: "%", min: 0, max: 90, classes: "enyo-fit slideable-sample right", onChange: "updateInfo"}, + {name: "bottom", kind: "Slideable", axis: "v", unit: "%", min: 0, max: 90, classes: "enyo-fit slideable-sample bottom", onChange: "updateInfo"}, + {name: "left", kind: "Slideable", axis: "h", unit: "%", min: -90, max: 0, classes: "enyo-fit slideable-sample left", onChange: "updateInfo"} + ], + handlers: { + ondragstart: "suppressPanelDrag" + }, + create: function() { + this.inherited(arguments); + var slideables = []; + + for (var c in this.$) { + if (this.$[c].kind === "Slideable") { + slideables.push(this.$[c]); + } + } + this.populate(slideables); + }, + populate: function(inSlideables) { + var slideable; + for (var s in inSlideables) { + slideable = inSlideables[s]; + slideable.createComponents([ + {style: slideable.axis === "h" ? "height: 38%;" : ""}, // cheating here for the horizontal Slideables to make everything nice and (almost) centered vertically + { + kind: "enyo.sample.SlideableInfo", + layoutKind: (slideable.axis === "v") ? enyo.FittableColumnsLayout : enyo.FittableRowsLayout, + classes: "enyo-center", // cheating here for the vertical Slideables to make everything nice and centered horizontally (no effect on horizontal Slideables) + info: { + name: slideable.name, + axis: slideable.axis, + unit: slideable.unit, + min: slideable.min, + max: slideable.max, + value: slideable.value + } + } + ]); + } + }, + updateInfo: function(inSender) { + inSender.waterfallDown("onUpdateInfo", { + name: inSender.name, + axis: inSender.axis, + unit: inSender.unit, + min: inSender.min, + max: inSender.max, + value: Math.round(inSender.value) + }); + return true; + }, + // keeps the view panel from moving in Sampler app while dragging the Slideable + suppressPanelDrag: function() { + return true; + } +}); + +enyo.kind({ + name: "enyo.sample.SlideableInfo", + kind: enyo.Control, + published: { + info: null + }, + components: [ + {kind: enyo.FittableRows, classes: "slideableinfo-sample", components: [ + {name: "name"}, + {name: "axis"}, + {name: "unit"}, + {name: "min"}, + {name: "max"}, + {name: "value"} + ]} + ], + handlers: { + onUpdateInfo: "updateInfo" + }, + create: function() { + this.inherited(arguments); + this.infoChanged(); + }, + infoChanged: function() { + for (var p in this.info) { + if (this.$[p]) { + this.$[p].setContent(enyo.cap(p) + ": " + this.info[p]); + } + } + }, + updateInfo: function(inSender, inEvent) { + this.setInfo(inEvent); + return true; + } +}); \ No newline at end of file diff --git a/lib/layout/slideable/samples/package.js b/lib/layout/slideable/samples/package.js new file mode 100644 index 0000000..1cbe4f8 --- /dev/null +++ b/lib/layout/slideable/samples/package.js @@ -0,0 +1,4 @@ +enyo.depends( + "SlideableSample.css", + "SlideableSample.js" +); \ No newline at end of file diff --git a/lib/layout/slideable/source/Slideable.js b/lib/layout/slideable/source/Slideable.js new file mode 100644 index 0000000..c5b3dc2 --- /dev/null +++ b/lib/layout/slideable/source/Slideable.js @@ -0,0 +1,316 @@ +/** + _enyo.Slideable_ is a control that can be dragged either horizontally or + vertically between a minimum and a maximum value. When released from + dragging, a Slideable will animate to its minimum or maximum position, + depending on the direction of the drag. + + The _min_ value specifies a position to the left of, or above, the initial + position, to which the Slideable may be dragged. + The _max_ value specifies a position to the right of, or below, the initial + position, to which the Slideable may be dragged. + The _value_ property specifies the current position of the Slideable, + between the minimum and maximum positions. + + _min_, _max_, and _value_ may be specified in units of "px" or "%". + + The _axis_ property determines whether the Slideable slides left-to-right + ("h") or up-and-down ("v"). + + The following control is placed 90% off the screen to the right, and slides + to its natural position. + + {kind: "enyo.Slideable", value: -90, min: -90, unit: "%", + classes: "enyo-fit", style: "width: 300px;", + components: [ + {content: "stuff"} + ] + } +*/ +enyo.kind({ + name: "enyo.Slideable", + kind: "Control", + published: { + //* Direction of sliding; can be "h" or "v" + axis: "h", + //* Current position of the Slideable (a value between _min_ and _max_) + value: 0, + //* Unit for _min_, _max_, and _value_; can be "px" or "%" + unit: "px", + //* A minimum value to slide to + min: 0, + //* A maximum value to slide to + max: 0, + //* When truthy, apply CSS styles to allow GPU compositing of slideable content + //* if the platform allows. + accelerated: "auto", + //* Set to false to prevent the Slideable from dragging with elasticity + //* past its _min_ or _max_ value + overMoving: true, + //* Set to false to disable dragging + draggable: true + }, + events: { + //* Fires when the Slideable finishes animating. + onAnimateFinish: "", + //* Fires when the position (i.e., _value_) of the Slideable changes. + onChange: "" + }, + //* Set to true to prevent a drag from bubbling beyond the Slideable + preventDragPropagation: false, + //* @protected + tools: [ + {kind: "Animator", onStep: "animatorStep", onEnd: "animatorComplete"} + ], + handlers: { + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish" + }, + kDragScalar: 1, + dragEventProp: "dx", + unitModifier: false, + canTransform: false, + //* @protected + create: function() { + this.inherited(arguments); + this.acceleratedChanged(); + this.transformChanged(); + this.axisChanged(); + this.valueChanged(); + this.addClass("enyo-slideable"); + }, + initComponents: function() { + this.createComponents(this.tools); + this.inherited(arguments); + }, + rendered: function() { + this.inherited(arguments); + this.canModifyUnit(); + this.updateDragScalar(); + }, + resizeHandler: function() { + this.inherited(arguments); + this.updateDragScalar(); + }, + canModifyUnit: function() { + if (!this.canTransform) { + var b = this.getInitialStyleValue(this.hasNode(), this.boundary); + // If inline style of "px" exists, while unit is "%" + if (b.match(/px/i) && (this.unit === "%")) { + // Set unitModifier - used to over-ride "%" + this.unitModifier = this.getBounds()[this.dimension]; + } + } + }, + getInitialStyleValue: function(inNode, inBoundary) { + var s = enyo.dom.getComputedStyle(inNode); + if (s) { + return s.getPropertyValue(inBoundary); + } else if (inNode && inNode.currentStyle) { + return inNode.currentStyle[inBoundary]; + } + return "0"; + }, + updateBounds: function(inValue, inDimensions) { + var inBounds = {}; + inBounds[this.boundary] = inValue; + this.setBounds(inBounds, this.unit); + + this.setInlineStyles(inValue, inDimensions); + }, + updateDragScalar: function() { + if (this.unit == "%") { + var d = this.getBounds()[this.dimension]; + this.kDragScalar = d ? 100 / d : 1; + + if (!this.canTransform) { + this.updateBounds(this.value, 100); + } + } + }, + transformChanged: function() { + this.canTransform = enyo.dom.canTransform(); + }, + acceleratedChanged: function() { + if (!(enyo.platform.android > 2)) { + enyo.dom.accelerate(this, this.accelerated); + } + }, + axisChanged: function() { + var h = this.axis == "h"; + this.dragMoveProp = h ? "dx" : "dy"; + this.shouldDragProp = h ? "horizontal" : "vertical"; + this.transform = h ? "translateX" : "translateY"; + this.dimension = h ? "width" : "height"; + this.boundary = h ? "left" : "top"; + }, + setInlineStyles: function(inValue, inDimensions) { + var inBounds = {}; + + if (this.unitModifier) { + inBounds[this.boundary] = this.percentToPixels(inValue, this.unitModifier); + inBounds[this.dimension] = this.unitModifier; + this.setBounds(inBounds); + } else { + if (inDimensions) { + inBounds[this.dimension] = inDimensions; + } else { + inBounds[this.boundary] = inValue; + } + this.setBounds(inBounds, this.unit); + } + }, + valueChanged: function(inLast) { + var v = this.value; + if (this.isOob(v) && !this.isAnimating()) { + this.value = this.overMoving ? this.dampValue(v) : this.clampValue(v); + } + // FIXME: android cannot handle nested compositing well so apply acceleration only if needed + // desktop chrome doesn't like this code path so avoid... + if (enyo.platform.android > 2) { + if (this.value) { + if (inLast === 0 || inLast === undefined) { + enyo.dom.accelerate(this, this.accelerated); + } + } else { + enyo.dom.accelerate(this, false); + } + } + + // If platform supports transforms + if (this.canTransform) { + enyo.dom.transformValue(this, this.transform, this.value + this.unit); + // else update inline styles + } else { + this.setInlineStyles(this.value, false); + } + this.doChange(); + }, + getAnimator: function() { + return this.$.animator; + }, + isAtMin: function() { + return this.value <= this.calcMin(); + }, + isAtMax: function() { + return this.value >= this.calcMax(); + }, + calcMin: function() { + return this.min; + }, + calcMax: function() { + return this.max; + }, + clampValue: function(inValue) { + var min = this.calcMin(); + var max = this.calcMax(); + return Math.max(min, Math.min(inValue, max)); + }, + dampValue: function(inValue) { + return this.dampBound(this.dampBound(inValue, this.min, 1), this.max, -1); + }, + dampBound: function(inValue, inBoundary, inSign) { + var v = inValue; + if (v * inSign < inBoundary * inSign) { + v = inBoundary + (v - inBoundary) / 4; + } + return v; + }, + percentToPixels: function(value, dimension) { + return Math.floor((dimension / 100) * value); + }, + pixelsToPercent: function(value) { + var boundary = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; + return (value / boundary) * 100; + }, + // dragging + shouldDrag: function(inEvent) { + return this.draggable && inEvent[this.shouldDragProp]; + }, + isOob: function(inValue) { + return inValue > this.calcMax() || inValue < this.calcMin(); + }, + dragstart: function(inSender, inEvent) { + if (this.shouldDrag(inEvent)) { + inEvent.preventDefault(); + this.$.animator.stop(); + inEvent.dragInfo = {}; + this.dragging = true; + this.drag0 = this.value; + this.dragd0 = 0; + return this.preventDragPropagation; + } + }, + drag: function(inSender, inEvent) { + if (this.dragging) { + inEvent.preventDefault(); + var d = this.canTransform ? inEvent[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(inEvent[this.dragMoveProp]); + var v = this.drag0 + d; + var dd = d - this.dragd0; + this.dragd0 = d; + if (dd) { + inEvent.dragInfo.minimizing = dd < 0; + } + this.setValue(v); + return this.preventDragPropagation; + } + }, + dragfinish: function(inSender, inEvent) { + if (this.dragging) { + this.dragging = false; + this.completeDrag(inEvent); + inEvent.preventTap(); + return this.preventDragPropagation; + } + }, + completeDrag: function(inEvent) { + if (this.value !== this.calcMax() && this.value != this.calcMin()) { + this.animateToMinMax(inEvent.dragInfo.minimizing); + } + }, + // animation + isAnimating: function() { + return this.$.animator.isAnimating(); + }, + play: function(inStart, inEnd) { + this.$.animator.play({ + startValue: inStart, + endValue: inEnd, + node: this.hasNode() + }); + }, + //* @public + //* Animates to the given value. + animateTo: function(inValue) { + this.play(this.value, inValue); + }, + //* Animates to the minimum value. + animateToMin: function() { + this.animateTo(this.calcMin()); + }, + //* Animates to the maximum value. + animateToMax: function() { + this.animateTo(this.calcMax()); + }, + //* @protected + animateToMinMax: function(inMin) { + if (inMin) { + this.animateToMin(); + } else { + this.animateToMax(); + } + }, + animatorStep: function(inSender) { + this.setValue(inSender.value); + return true; + }, + animatorComplete: function(inSender) { + this.doAnimateFinish(inSender); + return true; + }, + //* @public + //* Toggles between _min_ and _max_ values with animation. + toggleMinMax: function() { + this.animateToMinMax(!this.isAtMin()); + } +}); diff --git a/lib/layout/slideable/source/package.js b/lib/layout/slideable/source/package.js new file mode 100644 index 0000000..8c4ec43 --- /dev/null +++ b/lib/layout/slideable/source/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "Slideable.js" +); diff --git a/lib/layout/tree/package.js b/lib/layout/tree/package.js new file mode 100644 index 0000000..1ec0cd0 --- /dev/null +++ b/lib/layout/tree/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "source" +); \ No newline at end of file diff --git a/lib/layout/tree/samples/TreeSample.css b/lib/layout/tree/samples/TreeSample.css new file mode 100644 index 0000000..e69de29 diff --git a/lib/layout/tree/samples/TreeSample.html b/lib/layout/tree/samples/TreeSample.html new file mode 100644 index 0000000..e9af7ab --- /dev/null +++ b/lib/layout/tree/samples/TreeSample.html @@ -0,0 +1,22 @@ + + + + + Tree Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/tree/samples/TreeSample.js b/lib/layout/tree/samples/TreeSample.js new file mode 100644 index 0000000..eb203cc --- /dev/null +++ b/lib/layout/tree/samples/TreeSample.js @@ -0,0 +1,43 @@ +enyo.kind({ + name: "enyo.sample.TreeSample", + classes: "enyo-unselectable enyo-fit", + kind: "FittableRows", + fit: true, + components: [ + {kind: "Selection", onSelect: "select", onDeselect: "deselect"}, + {kind: "Scroller", fit: true, components: [ + {kind: "Node", icon: "assets/folder-open.png", content: "Tree", expandable: true, expanded: true, onExpand: "nodeExpand", onNodeTap: "nodeTap", components: [ + {icon: "assets/file.png", content: "Alpha"}, + {icon: "assets/folder-open.png", content: "Bravo", expandable: true, expanded: true, components: [ + {icon: "assets/file.png", content: "Bravo-Alpha"}, + {icon: "assets/file.png", content: "Bravo-Bravo"}, + {icon: "assets/file.png", content: "Bravo-Charlie"} + ]}, + {icon: "assets/folder.png", content: "Charlie", expandable: true, components: [ + {icon: "assets/file.png", content: "Charlie-Alpha"}, + {icon: "assets/file.png", content: "Charlie-Bravo"}, + {icon: "assets/file.png", content: "Charlie-Charlie"} + ]}, + {icon: "assets/folder-open.png", content: "Delta", expandable: true, expanded: true, components: [ + {icon: "assets/file.png", content: "Delta-Alpha"}, + {icon: "assets/file.png", content: "Delta-Bravo"}, + {icon: "assets/file.png", content: "Delta-Charlie"} + ]}, + {icon: "assets/file.png", content: "Epsilon"} + ]} + ]} + ], + nodeExpand: function(inSender, inEvent) { + inSender.setIcon("assets/" + (inSender.expanded ? "folder-open.png" : "folder.png")); + }, + nodeTap: function(inSender, inEvent) { + var node = inEvent.originator; + this.$.selection.select(node.id, node); + }, + select: function(inSender, inEvent) { + inEvent.data.$.caption.applyStyle("background-color", "lightblue"); + }, + deselect: function(inSender, inEvent) { + inEvent.data.$.caption.applyStyle("background-color", null); + } +}); \ No newline at end of file diff --git a/lib/layout/tree/samples/assets/file.png b/lib/layout/tree/samples/assets/file.png new file mode 100644 index 0000000000000000000000000000000000000000..98bbf1298f239c39a43b364c79c7da1e52b99287 GIT binary patch literal 609 zcmV-n0-pVeP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00GfSL_t(IPnDBdiyA=`Mu+4n!~9!+fZ(Hf z2qXyN4ldnj%cLJBcJNIw?S?3>gO&>#6-A*tDvHaOx;;!yg0mzAhc0?K_0_H0S66)a z{r=lzGRYE&ghf0aw}{1J_b!*~3!lHI_g) zcL&2Xuvjdhs;cK%fh0+6I2?j8CLkFJzN#u;_+d~IP18PINO-Z>cs#~nFc6T81WJOE zKMd0_EJ-Sr`uvw98jZ5qY-T-tgc4P&RmhSIzC}oX5DtgobUHr@3BSRX%O$4MsbDgh zpwsQ3R;!^{EJFXGBb&_%+-~;;#b5JT0QL28wZ=Fz~P_T}eFS-(f zU@*wm>or!Z)diG{ATia6j+^QeiA0t{5C{a=e!qulny*3&P%45K{z>5T`Pk`n!e+C1 z6-r54r7JJ&lfdisGCHQ+ZuchJ?H1?r8NB^31;^tNZ*e#rte#L5MF?*A&oUF;@{beV v)*D{L4^+q-o6S~mI2`yN>~{M-|MvPf5v#%NgV_W800000NkvXXu0mjfn)3vQ literal 0 HcmV?d00001 diff --git a/lib/layout/tree/samples/assets/folder-open.png b/lib/layout/tree/samples/assets/folder-open.png new file mode 100644 index 0000000000000000000000000000000000000000..ffd07a4865601705af5ee8a685fd09d60c728583 GIT binary patch literal 817 zcmV-11J3-3P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00N;&L_t(IPo-ECra{XgzX$cCN22Fatz7LwY(l6UCkS6VAb4d*S*IQR4m)`53wYRK z`@?B*{K{*!doRl7yQm6b8Txv=K{vdFsKbnRlOCvb9<-1AK(p43dW{p3?(Yz(Z7A)u zBEQvyY?Tq|jRwS58P!x7zXYu>o`EZBgSf{9PP+wZ&rP^Z2CmnC!{w*bI9EM^IN>-> z2*wc28wR^*7}0`>-%&Zb1nN<70VHB6?u#`Lb~$jT$$(o823%92koSmuOOcm#4gTt30Q#p-v)eKVVrjacBg2b9h#62EEY{>`?7Y-q^ zK#K#p0|>v@hdo>^!cyL6F|SdOlYy&+ZMa!)M3Qt0iPbusCc)@p63QRMLCyg7J?KYx zh6bUjy$DJDfE_n_oZI76L5zT#m4*w#AtcczoT-|^F~K<4C1W^LG=ly4TI|jqL|E1* zgrxU_byovcY9E46HOiO&LIAZbifi3@z8U@!l%R5N3_hDi1RDr}KG6|E%rdclp7)Zu vfR!H^P7b>WzI{Eu`buy0Oem>uC2aW%*(~qaPl}Ji00000NkvXXu0mjfdV6bJ literal 0 HcmV?d00001 diff --git a/lib/layout/tree/samples/assets/folder.png b/lib/layout/tree/samples/assets/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..17308c1edba308c00adf04f1accf8afd0341e942 GIT binary patch literal 808 zcmV+@1K0eCP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00NjvL_t(IPo;V+-ReDDiGf+WO}UB+XMnmhc+$sI>+AGM|uZ&w)ou zTvAA?8>OY=)gw4m?k(=T(T~W2K17w6Xr2l((glpVp&k(zTEN#@a8fafqgCXZvSGwZ zK44Gr0HO-}5Run|@ax?O%j!Z{{s_tIy@E^pRHml78X-v_l+JTLfKhN04w3+Y&WifgtVNa%pKP0uz)tp 0; + }, + fetchParent: function() { + return this.level > 0 && this.container.container; + }, + fetchChildren: function() { + return this.$.list && this.$.list.controls; + }, + fetchFirstChild: function() { + return this.$.list && this.$.list.controls[0]; + }, + fetchLastChild: function() { + return this.$.list && this.$.list.controls[this.$.list.controls.length-1]; + }, + fetchPrevSibling: function() { + var i = this.container.controls.indexOf(this); + return this.level > 0 && this.container.controls[i-1]; + }, + fetchNextSibling: function() { + var i = this.container.controls.indexOf(this); + return this.level > 0 && this.container.controls[i+1]; + }, + getVisibleBounds: function() { + return this.$.client.getBounds(); + } + */ +}); \ No newline at end of file diff --git a/lib/layout/tree/source/package.js b/lib/layout/tree/source/package.js new file mode 100644 index 0000000..5986bea --- /dev/null +++ b/lib/layout/tree/source/package.js @@ -0,0 +1,4 @@ +enyo.depends( + "Node.css", + "Node.js" +); \ No newline at end of file diff --git a/lib/onyx/CONTRIBUTING md b/lib/onyx/CONTRIBUTING md new file mode 100644 index 0000000..d0a3e5c --- /dev/null +++ b/lib/onyx/CONTRIBUTING md @@ -0,0 +1,44 @@ +# Contributions + +Contributions are welcome for Enyo and its associated libraries including onyx and layout. + +Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details +on our contribution policy and guidelines for use of the Enyo-DCO-1.0-Signed-off-by +line in your commits and pull requests. + +If you're interested in introducing new kinds, you might also consider hosting your own repo +and contributing to the [Enyo community gallery](http://enyojs.com/gallery). + +## Modifications to CSS + +Onyx CSS is defined using parameterized LESS files. Whenever you make changes to LESS files in Onyx, you'll also need to re-generate and check-in the top-level .css file as well, to maintain backward-compatibility for environments that don't wish to use LESS. + +You can re-generate the top-level onyx.css file as follows: + + cd lib/onyx/css + ../../../enyo/tools/lessc.sh ./package.js + +NOTE: Since LESS generates relative URLs, it's important to run the `lessc.sh` script from the onyx css folder. + +Also note you only need to generate the .css file when you're ready to check in your changes. During development, you can do all your testing modifying just LESS files if you include "less-xyz.min.js" in your app's debug.html file, which compiles the LESS client-side during loading: + + + +Additionally, any new controls contributed should follow this basic pattern to ensure proper themability support: + +* Place control's .js file(s) in `lib/onyx/source` and add to `lib/onyx/source/package.js` +* Place control's .less file(s) in `lib/onyx/css` +* @import .less file(s) into [`lib/onyx/css/onyx-rules.less`](https://github.com/enyojs/onyx/blob/master/css/onyx-rules.less) +* Use existing variables from [`lib/onyx/css/onyx-variables.less`](https://github.com/enyojs/onyx/blob/master/css/onyx-variables.less) in your control's LESS files when available, add any new variables your particular control needs along with their default definitions to onyx-variables.less. + +Refer to the [UI Theming Guide](https://github.com/enyojs/enyo/wiki/UI-Theming) for more details. + +## Samples + +Every new control should be accompanied by at least one sample in the [Enyo 2 Sampler](http://enyojs.com/sampler). Read the [Sampler readme](https://github.com/enyojs/sampler) for details on how to go about adding new samples to the Sampler. + +Guidelines for samples: + +* Samples should live in a folder named `samples`, as a peer to the source +* Be sure to exercise useful API's and events of the control in the sample +* When one or more significantly different or interesting configurations of the control are available, include more than one instance in the sample to exhibit use of the different API's diff --git a/lib/onyx/LICENSE-2.0.txt b/lib/onyx/LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/lib/onyx/LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/onyx/README.md b/lib/onyx/README.md new file mode 100644 index 0000000..9dc580e --- /dev/null +++ b/lib/onyx/README.md @@ -0,0 +1,29 @@ +### Looking for the issue tracker? +It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). + +--- + +## Onyx UI Library + +Onyx is a UI library for Enyo 2. + +We originally set out to adapt the Enyo 1 widgets for use with Enyo 2, but we quickly determined that we could achieve better cross-platform compatibility and build a more solid foundation for the future by starting with a clean slate. The result is a new UI library for Enyo 2 called **Onyx**. + +Despite the changes under the hood, you'll find that Onyx is clearly an evolution of the Enyo 1 UI from a design point of view. This first Onyx release features a variety of commonly used widgets, including toolbars, text inputs, checkboxes, groups and multiple types of buttons. Onyx also includes a base `Slideable` control that you can use to implement views that slide back and forth between pre-defined positions, including on and off screen. + +To get a feel for Onyx, check out the [OnyxSampler example](http://enyojs.com/samples/onyxsampler). Needless to say, we're not done -- we'll be expanding the Onyx widget set as we go. + +## Changes + +Any time you commit a change to a `.less` file, you also need to +re-generate the top-level library `.css` file as follows: + + cd lib/onyx/css + ../../enyo/tools/lessc.sh ./package.js + +This command will generate a new `onyx.css`, which you should check in +with your `.less` changes. + +Please don't manually edit the top-level `onyx.css`: those should be +treated as output files, and we should only be making changes to +`.less` files and generating the `.css` file using the above command. diff --git a/lib/onyx/css/Button.less b/lib/onyx/css/Button.less new file mode 100644 index 0000000..c9d6f87 --- /dev/null +++ b/lib/onyx/css/Button.less @@ -0,0 +1,71 @@ +/* Button.css */ +.onyx-button { + outline: 0; + /**/ + color: @onyx-button-text-color; + font-size: @onyx-button-font-size; + text-align: center; + white-space: nowrap; + /**/ + margin: 0; + padding: @onyx-button-padding-tb @onyx-button-padding-lr; + overflow: hidden; + /**/ + border-radius: @onyx-button-border-radius; + /* for IE8 */ + border: 1px solid (@onyx-button-background * 0.498); + border: 1px solid fade((@onyx-button-background * 0.067), 20%); + /* + The border and the gradient interact in a strange way that + causes the bottom-border (top if the gradient is aligned top) + to be lighter than other borders. + We can fix it by using the darker bottom border below, but + then there are a few rogue pixels that end up very dark. + */ + /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ + box-shadow: inset 0px 1px 0px rgba(255,255,255,0.2); + /**/ + background: @onyx-button-background @onyx-button-gradient repeat-x bottom; + background-size: contain; + /**/ + text-overflow: ellipsis; + /* the following cause arcane problems on IE */ + /* + min-width: 14px; + min-height: 20px; + */ +} + +/* + IE8 can't handle these selectors in tandem: + .onyx-button.active, .onyx-button:active:not([disabled]) { + + the effect is as if .onyx-button.active doesn't exist +*/ +.onyx-button.active, .onyx-button.pressed { + background-image: @onyx-button-active-gradient; + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0,0,0,0.1); +} + +.onyx-button:active:hover:not([disabled]) { + background-image: @onyx-button-active-gradient; + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0,0,0,0.1); +} + +.onyx-button[disabled] { + opacity: @onyx-disabled-opacity; + filter: alpha(opacity=@onyx-disabled-opacity-ie); +} + +.onyx-button > img { + padding: 0px 3px; +} + +/* Remove the focused inner-border style in Firefox (Windows) */ +.onyx-button::-moz-focus-inner { + border: 0; +} \ No newline at end of file diff --git a/lib/onyx/css/ButtonColors.less b/lib/onyx/css/ButtonColors.less new file mode 100644 index 0000000..f7ae783 --- /dev/null +++ b/lib/onyx/css/ButtonColors.less @@ -0,0 +1,25 @@ +/* ButtonColors.css */ +.onyx-button.onyx-blue { + background-color: #35A8EE; + color: #F2F2F2; +} + +.onyx-button.onyx-affirmative { + background-color: #91BA07; + color: #F2F2F2; +} + +.onyx-button.onyx-negative { + background-color: #C51616; + color: #F2F2F2; +} + +.onyx-button.onyx-dark { + background-color: @onyx-dark-background; + color: #F2F2F2; +} + +.onyx-button.onyx-light { + background-color: @onyx-light-background; + color: #2F2F2F; +} \ No newline at end of file diff --git a/lib/onyx/css/Checkbox.less b/lib/onyx/css/Checkbox.less new file mode 100644 index 0000000..dea796c --- /dev/null +++ b/lib/onyx/css/Checkbox.less @@ -0,0 +1,20 @@ +/* Checkbox.css */ +.onyx-checkbox { + cursor: pointer; + height: @onyx-checkbox-image-height; + width: @onyx-checkbox-image-width; + background: @onyx-checkbox-image no-repeat; + /* reset for ? */ + margin: 0px; + /* these entries cause toggle-button and checkbox to line up properly*/ + display: inline-block; + vertical-align: middle; +} + +.onyx-checkbox[checked] { + background-position: 0px -@onyx-checkbox-image-height; +} + +.onyx-checkbox[disabled] { + opacity: @onyx-disabled-opacity; +} diff --git a/lib/onyx/css/ContextualPopup.less b/lib/onyx/css/ContextualPopup.less new file mode 100644 index 0000000..9a1fdfb --- /dev/null +++ b/lib/onyx/css/ContextualPopup.less @@ -0,0 +1,230 @@ +/* ContextualPopup.css */ +.onyx-contextual-popup-title { + font-weight:bold; + padding:24px 32px 0px; +} +.onyx-contextual-popup-scroller { + padding:24px 32px; +} +.onyx-contextual-popup-action-buttons { + display:inline-block; + width:100%; + text-align: center; +} +.onyx-contextual-popup-action-button { + margin-left: 5px; + margin-right: 5px; +} +.onyx-contextual-popup, +.onyx.onyx-contextual-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c; +} +/*setup the nub*/ +.onyx-contextual-popup::after{ + content: ''; + position: absolute; + top: -10px; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; +} +/*for popups above activator*/ +.onyx-contextual-popup.vertical.above { + top: auto; + margin-top:-10px; + bottom: 100%; + margin-bottom: 10px; +} +/*for popups below activator*/ +.onyx-contextual-popup.vertical.below { + margin-top:10px; +} +/*for popups on the left of the activator*/ +.onyx-contextual-popup.right.horizontal { + margin-left: -11px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.left.horizontal { + margin-left: 10px; +} +/*nub positioning*/ +/*horizontally centered nub*/ +.onyx-contextual-popup.vertical::after { + position:absolute; + left:45%; + border-bottom: 10px solid #4c4c4c; + border-top: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +/*nub near horizontal left*/ +.onyx-contextual-popup.vertical.right::after { + left:0%; + margin-left:20px; +} +/*nub near horizontal right*/ +.onyx-contextual-popup.vertical.left::after { + left:100%; + margin-left: -55px; +} +/*downward facing nub*/ +.onyx-contextual-popup.vertical.above::after { + top:100%; + border-top: 10px solid #4c4c4c; + border-bottom: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right::after { + top:0%; + margin-top:-10px; + border-bottom: 10px solid #4c4c4c; + border-left: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.left::after { + top:0%; + margin-top:-10px; + border-right: 10px solid transparent; +} +/*nub positioning for left/right popups*/ +/*vertically centered nub for popups on left of activator*/ +.onyx-contextual-popup.right::after { + left: 100%; + top:47%; + margin-right:20px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on left of activator*/ +.onyx-contextual-popup.right.high::after { + top: 35px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on left of activator*/ +.onyx-contextual-popup.right.low::after { + top:100%; + margin-top: -55px; + border-left: 10px solid #4C4C4C; +} +/*vertically centered nub for popups on right of activator*/ +.onyx-contextual-popup.left::after { + left: 0%; + margin-left: -20px; + top: 45%; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on right of activator*/ +.onyx-contextual-popup.left.high::after { + top: 35px; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on right of activator*/ +.onyx-contextual-popup.left.low::after { + top:100%; + margin-top: -55px; + border-right: 10px solid #4C4C4C; +} +/*corners*/ +/*vertical top corners*/ +/*for popups on the left of the activator*/ +.onyx-contextual-popup.vertical.right.corner { + margin-left: 0px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.vertical.left.corner { + margin-left: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.vertical.below.right.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner::after { + top:0%; + left:100%; + margin-top:-10px; + margin-left:-19px; + border-right: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right.corner::after { + top:0%; + left:0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +/*vertical bottom corners*/ +.onyx-contextual-popup.left.above.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.right.above.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.vertical.left.above.corner::after { + top:100%; + margin-left:-19px; + border-right: 10px solid #4C4C4C; + border-bottom: 10px solid transparent; + border-top: none; +} +.onyx-contextual-popup.vertical.right.above.corner::after { + top:100%; + left:0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-bottom: 10px solid transparent; + border-top: none; +} +/*horizontal bottom corners*/ +.onyx-contextual-popup.left.low.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.right.low.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.left.low.corner::after { + top:100%; + left:0%; + margin-top: -19px; + margin-left: -12px; + border-bottom: 10px solid #4c4c4c; + border-right: 10px solid #4c4c4c; +} +.onyx-contextual-popup.right.low.corner::after { + top:100%; + left:100%; + margin-top: -19px; + border-bottom: 10px solid#4c4c4c; + border-left: none; +} +/*horizontal top corners*/ +.onyx-contextual-popup.left.high.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.right.high.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.left.high.corner::after { + top:0%; + left:0%; + margin-top: -1px; + margin-left: -12px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +.onyx-contextual-popup.right.high.corner::after { + top:0%; + left:100%; + margin-top:-1px; + margin-left:-9px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} \ No newline at end of file diff --git a/lib/onyx/css/DatePicker.less b/lib/onyx/css/DatePicker.less new file mode 100644 index 0000000..3e4b282 --- /dev/null +++ b/lib/onyx/css/DatePicker.less @@ -0,0 +1,14 @@ +/* DatePicker.css */ +.onyx-datepicker-month { + min-width: 75px; +} + +.onyx-datepicker-day { + min-width: 60px; +} + +.onyx-datepicker-year { + min-width: 70px; +} + + diff --git a/lib/onyx/css/Grabber.less b/lib/onyx/css/Grabber.less new file mode 100644 index 0000000..c44362f --- /dev/null +++ b/lib/onyx/css/Grabber.less @@ -0,0 +1,7 @@ +/* Grabber.css */ +.onyx-grabber { + background: @onyx-grabber-image no-repeat center; + width: @onyx-grabber-image-width; + height: @onyx-grabber-image-height; +} + diff --git a/lib/onyx/css/Groupbox.less b/lib/onyx/css/Groupbox.less new file mode 100644 index 0000000..1195965 --- /dev/null +++ b/lib/onyx/css/Groupbox.less @@ -0,0 +1,67 @@ +/* Groupbox.css */ +.onyx-groupbox { +} + +.onyx-groupbox > * { + display: block; + /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ + border-color: #aaaaaa; + border-style: solid; + border-width: 0 1px 1px 1px; + /*padding: 10px;*/ + /* reset styles that make 'item' look bad if they happen to be there */ + border-radius: 0; + margin: 0; + font-size: @onyx-groupbox-font-size; +} + +.onyx-groupbox > *:first-child { + border-top-color: #aaaaaa; + border-width: 1px; + border-radius: @onyx-groupbox-border-radius @onyx-groupbox-border-radius 0 0; +} + +.onyx-groupbox > *:last-child { + border-radius: 0 0 @onyx-groupbox-border-radius @onyx-groupbox-border-radius; +} + +.onyx-groupbox > *:first-child:last-child { + border-radius: @onyx-groupbox-border-radius; +} + +.onyx-groupbox-header { + padding: 2px 10px; + /**/ + color: @onyx-groupbox-text-color; + font-size: @onyx-groupbox-header-font-size; + font-weight: bold; + text-transform: uppercase; + /**/ + background-color: @onyx-groupbox-background; + border: none; + background: @onyx-groupbox-background @onyx-groupbox-gradient repeat-x 0 10px; +} + +.onyx-groupbox .onyx-input-decorator { + display: block; +} + +.onyx-groupbox > .onyx-input-decorator { + border-color: #aaaaaa; + border-width: 0 1px 1px 1px; + border-radius: 0; +} + +.onyx-groupbox > .onyx-input-decorator:first-child { + border-width: 1px; + border-radius: @onyx-groupbox-border-radius @onyx-groupbox-border-radius 0 0; +} + +.onyx-groupbox > .onyx-input-decorator:last-child { + border-radius: 0 0 @onyx-groupbox-border-radius @onyx-groupbox-border-radius; +} + +.onyx-groupbox > .onyx-input-decorator:first-child:last-child { + border-radius: @onyx-groupbox-border-radius; +} + diff --git a/lib/onyx/css/Icon.less b/lib/onyx/css/Icon.less new file mode 100644 index 0000000..c18e00b --- /dev/null +++ b/lib/onyx/css/Icon.less @@ -0,0 +1,21 @@ +/* Icon.css */ +.onyx-icon, .onyx-icon-toggle { + width: @onyx-icon-size; + height: @onyx-icon-size; + background-repeat: no-repeat; + display: inline-block; + vertical-align: middle; +} + +.onyx-icon.onyx-icon-button.active, .onyx-icon.onyx-icon-button.pressed, .onyx-icon.onyx-icon-button:active:hover, .onyx-icon-toggle.active { + background-position: 0 -@onyx-icon-size; +} + +.onyx-icon.disabled { + opacity: @onyx-disabled-opacity; + filter: alpha(opacity=@onyx-disabled-opacity-ie); +} + +.onyx-icon.disabled:active:hover { + background-position: 0 0px; +} diff --git a/lib/onyx/css/Input.less b/lib/onyx/css/Input.less new file mode 100644 index 0000000..f0d5162 --- /dev/null +++ b/lib/onyx/css/Input.less @@ -0,0 +1,45 @@ +/* Input.css */ +.onyx-input-decorator { + padding: 6px 8px 10px 8px; + border-radius: @onyx-input-border-radius; + border: 1px solid; + border-color: rgba(0,0,0,0.1); + margin: 0; +} + +.onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0,0,0,0.3); + border-color: rgba(0,0,0,0.3); + background-color: @onyx-input-focused-background; +} + +.onyx-input-decorator.onyx-disabled { + /* FIXME: needed to color a disabled input placeholder. */ + /*-webkit-text-fill-color: #888;*/ + opacity: @onyx-disabled-opacity; + filter: alpha(opacity=@onyx-disabled-opacity-ie); +} + +.onyx-input-decorator > input { + /* reset */ + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: @onyx-input-background; + background-image: none; + font-size: @onyx-input-font-size; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + /* -webkit-appearance: caret;*/ +} + +.onyx-input-decorator.onyx-focused > input { + cursor: text; +} + +.onyx-input-decorator.onyx-disabled > input { + cursor: default; +} + diff --git a/lib/onyx/css/Item.less b/lib/onyx/css/Item.less new file mode 100644 index 0000000..7b95026 --- /dev/null +++ b/lib/onyx/css/Item.less @@ -0,0 +1,24 @@ +/* Item.css */ +.onyx-item { + padding: 14px; +} + +.onyx-highlight, .onyx-highlight.onyx-swipeable-item-content { + background-color: @onyx-highlight-background; +} + +.enyo-selected, .enyo-selected.onyx-swipeable-item-content { + background-color: @onyx-selected-background; +} + +.onyx-item.onyx-swipeable-item { + overflow: hidden; + padding: 0; +} + +.onyx-swipeable-item-content { + background-color: @onyx-switeable-item-background; + box-sizing: border-box; + padding: 18px 6px; + min-height: 40px; +} diff --git a/lib/onyx/css/Menu.less b/lib/onyx/css/Menu.less new file mode 100644 index 0000000..8cb8118 --- /dev/null +++ b/lib/onyx/css/Menu.less @@ -0,0 +1,64 @@ +/* Menu.css */ +.onyx-menu, .onyx.onyx-menu { + min-width: 160px; + top: 100%; + left: 0; + margin-top: 2px; + padding: 3px 0; + border-radius: @onyx-menu-border-radius; +} + +.onyx-menu.onyx-menu-up { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 2px; +} + +.onyx-toolbar .onyx-menu { + margin-top: 11px; + border-radius: 0 0 @onyx-menu-border-radius @onyx-menu-border-radius; +} + + +.onyx-toolbar .onyx-menu.onyx-menu-up { + margin-top: 0; + margin-bottom: 10px; + border-radius: @onyx-menu-border-radius @onyx-menu-border-radius 0 0; +} + +.onyx-menu-item { + display: block; + padding: 10px; +} + +.onyx-menu-item:hover { + background: @onyx-menu-item-hover; +} + +.onyx-menu-divider, .onyx-menu-divider:hover { + margin: 6px 0; + padding: 0; + border-bottom: 1px solid #aaa; +} + +.onyx-menu-label { + cursor: default; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + opacity: @onyx-disabled-opacity; + filter: alpha(opacity=@onyx-disabled-opacity-ie); +} + +.onyx-menu-label:hover { + background: none; +} + +/* customize a toolbar to support menus */ +.onyx-menu-toolbar, .onyx-toolbar.onyx-menu-toolbar { + position: relative; + z-index: 10; + overflow: visible; +} + diff --git a/lib/onyx/css/MoreToolbar.less b/lib/onyx/css/MoreToolbar.less new file mode 100644 index 0000000..8084c93 --- /dev/null +++ b/lib/onyx/css/MoreToolbar.less @@ -0,0 +1,30 @@ +/* MoreToolbar.css */ +.onyx-more-toolbar { + overflow: visible; + position: relative; + z-index: 10; +} + +.onyx-more-toolbar.active { + z-index:11; +} + +.onyx-more-menu { + left: auto; + right: 0px; + min-width: 0; +} + +.onyx-more-toolbar .onyx-more-menu > * { + float: right; + clear: both; + margin: 5px; + margin-top: 5px; + margin-bottom: 5px; +} + +.onyx-more-button { + background-image: @onyx-more-toolbar-button-image; + width: @onyx-more-toolbar-button-image-width; + height: @onyx-more-toolbar-button-image-height; +} diff --git a/lib/onyx/css/Picker.less b/lib/onyx/css/Picker.less new file mode 100644 index 0000000..8a3d545 --- /dev/null +++ b/lib/onyx/css/Picker.less @@ -0,0 +1,49 @@ +/* Picker.css */ +.onyx-picker-decorator .onyx-button { + padding: 10px 18px; +} + +.onyx-picker { + top: 0; + margin-top: -3px; + min-width: 0; + width: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + color: black; + background: @onyx-picker-background; +} + +.onyx-picker.onyx-menu-up { + top: auto; + bottom: 0; + margin-top: 3px; + margin-bottom: -3px; +} + +.onyx-picker .onyx-menu-item { + text-align: center; +} + +.onyx-picker .onyx-menu-item:hover { + background-color: transparent; +} + +.onyx-picker .onyx-menu-item.selected, .onyx-picker .onyx-menu-item.active, .onyx-picker .onyx-menu-item:active:hover { + border-top: 1px solid rgba(0, 0, 0, 0.1); + background-color: @onyx-picker-item-background; + box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); +} + +.onyx-picker .onyx-menu-item { + border-top: 1px solid rgba(255,255,255,0.5); + border-bottom: 1px solid rgba(0,0,0,0.2); +} + +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, .onyx-flyweight-picker :first-child > .onyx-menu-item { + border-top: none; +} + +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, .onyx-flyweight-picker :last-child > .onyx-menu-item { + border-bottom: none; +} diff --git a/lib/onyx/css/Popup.less b/lib/onyx/css/Popup.less new file mode 100644 index 0000000..7ed22ce --- /dev/null +++ b/lib/onyx/css/Popup.less @@ -0,0 +1,14 @@ +/* Popup.css */ +.onyx-popup { + font-size: @onyx-popup-font-size; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0,0,0,0.2); + border-radius: 8px; + padding: 6px; + color: @onyx-popup-text-color; + background: @onyx-popup-background @onyx-button-gradient repeat-x 0 bottom; +} + +.onyx-popup-decorator { + position: relative; +} diff --git a/lib/onyx/css/ProgressBar.less b/lib/onyx/css/ProgressBar.less new file mode 100644 index 0000000..f3c7c72 --- /dev/null +++ b/lib/onyx/css/ProgressBar.less @@ -0,0 +1,69 @@ +/* ProgressBar.css */ +.onyx-progress-bar { + margin: 8px; + height: 8px; + border: 1px solid rgba(15, 15, 15, 0.2); + border-radius: @onyx-progressbar-border-radius; + background: @onyx-progressbar-background @onyx-progressbar-gradient repeat-x; + background-size: auto 100%; +} + +.onyx-progress-bar-bar { + height: 100%; + border-radius: @onyx-progressbar-border-radius; + background: @onyx-progressbar-bar-background @onyx-progressbar-bar-gradient repeat-x; + background-size: auto 100%; +} + +.onyx-progress-bar-bar.striped { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +.onyx-progress-bar-bar.striped.animated { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} diff --git a/lib/onyx/css/ProgressButton.less b/lib/onyx/css/ProgressButton.less new file mode 100644 index 0000000..ace04d3 --- /dev/null +++ b/lib/onyx/css/ProgressButton.less @@ -0,0 +1,33 @@ +/* ProgressButton.css */ +.onyx-progress-button { + position: relative; + height: 36px; + line-height: 36px; + color: @onyx-progressbutton-text-color; + font-size: @onyx-progressbutton-font-size; + text-overflow: ellipsis; +} + +.onyx-progress-button-bar { + height: 36px; +} + +.onyx-progress-button-icon { + display: inline-block; + position: absolute; + top: 2px; + right: 0; +} + +.onyx-progress-button-client { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 36px; + margin-left: 8px; +} + +.onyx-progress-button-client > * { + display: inline-block; +} diff --git a/lib/onyx/css/RadioButton.less b/lib/onyx/css/RadioButton.less new file mode 100644 index 0000000..fb23e4f --- /dev/null +++ b/lib/onyx/css/RadioButton.less @@ -0,0 +1,37 @@ +/* RadioButton.css */ +.onyx-radiobutton { + padding: 8px 12px; + margin: 0; + outline: 0; + /**/ + font-size: @onyx-radiobutton-font-size; + text-shadow: 0 1px 1px rgba(0,0,0,0.2); + text-align: center; + /**/ + background: @onyx-radiobutton-background @onyx-radiobutton-gradient repeat-x bottom; + /* IE8 */ + border: 1px solid (@onyx-radiobutton-background * 0.22); + border: 1px solid fade((@onyx-radiobutton-background * 0.065), 20%); + /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ + border-right-color: rgba(0,0,0,0); + box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); +} + +.onyx-radiobutton:first-child { + border-radius: @onyx-radiobutton-border-radius 0 0 @onyx-radiobutton-border-radius; +} + +.onyx-radiobutton:last-child { + border-radius: 0px @onyx-radiobutton-border-radius @onyx-radiobutton-border-radius 0px; + /* IE8 */ + border-right: 1px solid (@onyx-radiobutton-background * 0.22); + border-right: 1px solid fade((@onyx-radiobutton-background * 0.065), 20%); +} + +.onyx-radiobutton.active { + color: @onyx-radiobutton-active-text-color; + background: @onyx-radiobutton-active-background @onyx-gradient-invert repeat-x top; + border-top: 1px solid fade((@onyx-radiobutton-background * 0.065), 60%); + box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); +} + diff --git a/lib/onyx/css/RangeSlider.less b/lib/onyx/css/RangeSlider.less new file mode 100644 index 0000000..4a556f9 --- /dev/null +++ b/lib/onyx/css/RangeSlider.less @@ -0,0 +1,10 @@ +/* RangeSlider.css */ +.onyx-range-slider-knob { + top: -17px; +} +.onyx-range-slider-label { + position: relative; + top: -18px; + text-align: center; + white-space: nowrap; +} diff --git a/lib/onyx/css/RichText.less b/lib/onyx/css/RichText.less new file mode 100644 index 0000000..e0e1492 --- /dev/null +++ b/lib/onyx/css/RichText.less @@ -0,0 +1,26 @@ +/* RichText.css */ +.onyx-input-decorator > .onyx-richtext { + /* reset */ + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: @onyx-input-background; + background-image: none; + font-size: @onyx-richtext-font-size; + min-height: 20px; + min-width: 100px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + /* -webkit-appearance: caret;*/ +} + +.onyx-input-decorator.onyx-focused > .onyx-richtext { + cursor: text; +} + +.onyx-input-decorator.onyx-disabled > .onyx-richtext { + cursor: default; +} + diff --git a/lib/onyx/css/Scrim.less b/lib/onyx/css/Scrim.less new file mode 100644 index 0000000..06b041a --- /dev/null +++ b/lib/onyx/css/Scrim.less @@ -0,0 +1,23 @@ +/* Scrim.css */ +.onyx-scrim { + z-index: 1; + /* + note: by using pointer-events we allow tapping on scrim + while it is fading out; however, this requires any showing classes + to set pointer events to auto or scrim will not function as expected. + */ + pointer-events: none; +} + +@onyx-scrim-opacity-ie: @onyx-scrim-opacity*100; +.onyx-scrim.onyx-scrim-translucent{ + pointer-events: auto; + background-color: @onyx-scrim-background; + opacity: @onyx-scrim-opacity; + filter: alpha(opacity=@onyx-scrim-opacity-ie); +} + +.onyx-scrim.onyx-scrim-transparent { + pointer-events: auto; + background: transparent; +} diff --git a/lib/onyx/css/Slider.less b/lib/onyx/css/Slider.less new file mode 100644 index 0000000..ff33960 --- /dev/null +++ b/lib/onyx/css/Slider.less @@ -0,0 +1,24 @@ +/* Slider.css */ +.onyx-slider { + position: relative; + margin: 8px 20px; +} + +.onyx-slider-taparea { + position: absolute; + top: -11px; + height: 28px; + width: 100%; +} + +.onyx-slider-knob { + position: relative; + height: @onyx-slider-knob-image-height; + width: @onyx-slider-knob-image-width; + background: @onyx-slider-knob-image left top no-repeat; + margin: -23px -20px; +} + +.onyx-slider-knob.active, .onyx-slider-knob.pressed, .onyx-slider-knob:active:hover { + background-position: 0 -40px; +} diff --git a/lib/onyx/css/Spinner.less b/lib/onyx/css/Spinner.less new file mode 100644 index 0000000..225a5dd --- /dev/null +++ b/lib/onyx/css/Spinner.less @@ -0,0 +1,11 @@ +/* Spinner.css */ +.onyx-spinner { + width: @onyx-spinner-image-width; + height: @onyx-spinner-image-height; + display: inline-block; + background: @onyx-spinner-dark-image no-repeat 0 0; +} + +.onyx-spinner.onyx-light { + background: @onyx-spinner-light-image no-repeat 0 0; +} diff --git a/lib/onyx/css/TabButton.less b/lib/onyx/css/TabButton.less new file mode 100644 index 0000000..7858b27 --- /dev/null +++ b/lib/onyx/css/TabButton.less @@ -0,0 +1,7 @@ +/* TabButton.css */ +.onyx-radiobutton.onyx-tabbutton { + padding: @onyx-tabbutton-padding-tb @onyx-tabbutton-padding-lr; + font-size: @onyx-tabbutton-font-size; + border-radius: 0px; +} + diff --git a/lib/onyx/css/TextArea.less b/lib/onyx/css/TextArea.less new file mode 100644 index 0000000..c6fa115 --- /dev/null +++ b/lib/onyx/css/TextArea.less @@ -0,0 +1,32 @@ +/* TextArea.css */ +.onyx-input-decorator > textarea { + /* reset */ + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: @onyx-input-background; + background-image: none; + font-size: @onyx-textarea-font-size; + box-shadow: none; + /* Remove scrollbars and resize handle */ + resize: none; + overflow: auto; + /* FIXME: hack for styling reset on Android */ + /* -webkit-appearance: caret;*/ +} + +.onyx-input-decorator.onyx-focused > textarea { + cursor: text; +} + +.onyx-input-decorator.onyx-disabled > textarea { + cursor: default; +} + +.onyx-textarea { + /* need >=50px for scrollbar to be usable on mac */ + min-height: 50px; +} + diff --git a/lib/onyx/css/TimePicker.less b/lib/onyx/css/TimePicker.less new file mode 100644 index 0000000..a3a973c --- /dev/null +++ b/lib/onyx/css/TimePicker.less @@ -0,0 +1,12 @@ +/* TimePicker.css */ +.onyx-timepicker-hour { + min-width: 60px; +} + +.onyx-timepicker-minute { + min-width: 60px; +} + +.onyx-timepicker-ampm { + min-width: 60px; +} \ No newline at end of file diff --git a/lib/onyx/css/ToggleButton.less b/lib/onyx/css/ToggleButton.less new file mode 100644 index 0000000..c297d71 --- /dev/null +++ b/lib/onyx/css/ToggleButton.less @@ -0,0 +1,65 @@ +/* ToggleButton.css */ +.onyx-toggle-button { + display: inline-block; + height: 32px; + line-height: 32px; + min-width: 64px; + vertical-align: middle; + text-align: center; + /* */ + border-radius: @onyx-togglebutton-border-radius; + box-shadow: inset 0px 1px 3px rgba(0,0,0,0.4); + background: @onyx-togglebutton-background @onyx-togglebutton-gradient repeat-x bottom; + background-size: auto 100%; + /* label */ + color: @onyx-togglebutton-text-color; + font-size: @onyx-togglebutton-font-size; + font-weight: bold; + text-transform: uppercase; +} + +.onyx-toggle-button.off { + background-color: @onyx-togglebutton-off-background !important; +} + +.onyx-toggle-button-knob { + display: inline-block; + width: 30px; + height: 30px; + margin: 1px; + border-radius: @onyx-togglebutton-border-radius; + background: @onyx-togglebutton-knob-background @onyx-togglebutton-knob-gradient repeat-x; + background-size: auto 100%; +} + +.onyx-toggle-button .onyx-toggle-button-knob { + box-shadow: -1px 0px 4px rgba(0,0,0,0.35), inset 0 -1px 0 rgba(0,0,0,0.4); + float: right; +} + +.onyx-toggle-button.off .onyx-toggle-button-knob { + box-shadow: 1px 0px 4px rgba(0,0,0,0.35), inset 0 -1px 0 rgba(0,0,0,0.4); + float: left; +} + +.onyx-toggle-button.disabled, .onyx-icon-button.disabled { + opacity: @onyx-disabled-opacity; + filter: alpha(opacity=@onyx-disabled-opacity-ie); +} + +.onyx-toggle-content { + min-width: 32px; + padding: 0 6px; +} + +.onyx-toggle-content.empty { + padding: 0; +} + +.onyx-toggle-content.off { + float: right; +} + +.onyx-toggle-content.on { + float: left; +} diff --git a/lib/onyx/css/Toolbar.less b/lib/onyx/css/Toolbar.less new file mode 100644 index 0000000..1e0448c --- /dev/null +++ b/lib/onyx/css/Toolbar.less @@ -0,0 +1,64 @@ +/* Toolbar.css */ +.onyx-toolbar { + /* + line-height is unreliable for centering, instead + use vertical-align: middle to align + elements along a common centerline and use + padding to fill out the space. + */ + padding: 9px 8px 10px 8px; + /**/ + border: 1px solid #3A3A3A; + background: @onyx-toolbar-background @onyx-toolbar-gradient repeat-x 0 bottom; + background-size: contain; + color: @onyx-toolbar-text-color; + /**/ + white-space: nowrap; + overflow-y: visible; + font-size: @onyx-toolbar-font-size; +} + +.onyx-toolbar-inline > *, .enyo-fittable-columns-layout.onyx-toolbar-inline > * { + display: inline-block; + vertical-align: middle; + margin: 4px 6px 5px; + box-sizing: border-box; +} + +.onyx-toolbar .onyx-icon-button { + margin: 3px 2px 1px; +} + +.onyx-toolbar .onyx-button { + color: @onyx-toolbar-button-text-color; + background-color: @onyx-toolbar-button-background; + border-color: rgba(15, 15, 15, 0.5); + margin-top: 0; + margin-bottom: 0; + height: 36px; +} + +.onyx-toolbar .onyx-input-decorator { + margin: 1px 3px; + box-shadow: inset 0px 1px 4px rgba(0,0,0,0.1); + background-color: @onyx-toolbar-input-background; + padding: 0px 6px 5px 6px; +} + +.onyx-toolbar .onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0,0,0,0.3); + background-color: @onyx-toolbar-input-focused-background; +} + +.onyx-toolbar .onyx-input-decorator .onyx-input { + color: @onyx-toolbar-input-text-color; + font-size: @onyx-toolbar-input-font-size; +} + +.onyx-toolbar .onyx-input-decorator .onyx-input:focus { + color: @onyx-toolbar-input-focus-text-color; +} + +.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { + color: @onyx-toolbar-input-placeholder-text-color; +} diff --git a/lib/onyx/css/Tooltip.less b/lib/onyx/css/Tooltip.less new file mode 100644 index 0000000..d4925b8 --- /dev/null +++ b/lib/onyx/css/Tooltip.less @@ -0,0 +1,70 @@ +/* Tooltip.css */ +.onyx-tooltip { + z-index: 20; + left: 0; + padding: 4px 6px; + margin-top: 4px; + margin-left: -6px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0,0,0,0.2); + color: @onyx-tooltip-text-color; + background: @onyx-tooltip-background @onyx-tooltip-gradient repeat-x 0 bottom; + border-radius: @onyx-tooltip-border-radius; + white-space: nowrap; +} + +/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ +.onyx-tooltip.right-arrow { + left: 30px; +} + +/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ +.onyx-tooltip::before { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + left: 16px; +} + +.onyx-tooltip::after { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + margin-left: -12px; +} + +/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ +.onyx-tooltip.below { + top: 100%; +} + +.onyx-tooltip.below.right-arrow::after { + border-bottom: 6px solid #1D587F; + top: -6px; +} + +.onyx-tooltip.below.left-arrow::before { + border-bottom: 6px solid #1D587F; + top: -6px; +} + +/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ +.onyx-tooltip.above { + top: -100%; +} + +.onyx-tooltip.above.right-arrow::after { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} + +.onyx-tooltip.above.left-arrow::before { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} \ No newline at end of file diff --git a/lib/onyx/css/onyx-rules.less b/lib/onyx/css/onyx-rules.less new file mode 100644 index 0000000..1b33f4a --- /dev/null +++ b/lib/onyx/css/onyx-rules.less @@ -0,0 +1,78 @@ +/* onyx-classes.less - combined CSS (less) files for all released Onyx controls + into single onyx.less file to avoid IE bug that allows + a maximum of 31 style sheets to be loaded before silently failing */ + +.onyx { + color: @onyx-text-color; + font-family: @onyx-font-family; + font-size: @onyx-font-size; + cursor: default; + background-color: @onyx-background; + /* remove automatic tap highlight color */ + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +/* prevent IE from inheriting line-height for these elements */ +.onyx button, .onyx label, .onyx input { + line-height: normal; +} + +.onyx-selected { + background-color: @onyx-selected-background; +} + +/* LESS pre-calculations */ +@onyx-disabled-opacity-ie: @onyx-disabled-opacity*100; + + +/* Individual Widget CSS */ + +@import "Icon.less"; +@import "Button.less"; +@import "Checkbox.less"; +@import "Grabber.less"; +@import "Popup.less"; +@import "Groupbox.less"; +@import "Input.less"; +@import "Menu.less"; +@import "Picker.less"; +@import "TextArea.less"; +@import "RichText.less"; +@import "RadioButton.less"; +@import "Scrim.less"; +@import "TabButton.less"; +@import "ToggleButton.less"; +@import "Toolbar.less"; +@import "Tooltip.less"; +@import "ProgressBar.less"; +@import "ProgressButton.less"; +@import "Slider.less"; +@import "RangeSlider.less"; +@import "Item.less"; +@import "Spinner.less"; +@import "MoreToolbar.less"; +@import "DatePicker.less"; +@import "TimePicker.less"; +@import "ButtonColors.less"; +@import "ContextualPopup.less"; + +/* some default colors */ +.onyx-dark { + background-color: @onyx-dark-background; +} + +.onyx-light { + background-color: @onyx-light-background; +} + +.onyx-green { + background-color: #91BA07; +} + +.onyx-red { + background-color: #C51616; +} + +.onyx-blue { + background-color: #35A8EE; +} \ No newline at end of file diff --git a/lib/onyx/css/onyx-variables.less b/lib/onyx/css/onyx-variables.less new file mode 100644 index 0000000..2add963 --- /dev/null +++ b/lib/onyx/css/onyx-variables.less @@ -0,0 +1,140 @@ +/* Fonts */ +/* ---------------------------------------*/ +@onyx-font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; +@onyx-font-size-small: 14px; +@onyx-font-size-medium: 16px; +@onyx-font-size-large: 20px; + +@onyx-button-font-size: @onyx-font-size-medium; +@onyx-font-size: @onyx-font-size-large; +@onyx-groupbox-font-size: @onyx-font-size-medium; +@onyx-groupbox-header-font-size: @onyx-font-size-small; +@onyx-input-font-size: @onyx-font-size-medium; +@onyx-popup-font-size: @onyx-font-size-medium; +@onyx-progressbutton-font-size: @onyx-font-size-medium; +@onyx-radiobutton-font-size: @onyx-font-size-medium; +@onyx-richtext-font-size: @onyx-font-size-medium; +@onyx-tabbutton-font-size: @onyx-font-size-large; +@onyx-textarea-font-size: @onyx-font-size-medium; +@onyx-togglebutton-font-size: @onyx-font-size-small; +@onyx-toolbar-font-size: @onyx-font-size-large; +@onyx-toolbar-input-font-size: @onyx-font-size-small; + +/* Text Colors */ +/* ---------------------------------------*/ +@onyx-button-text-color: #292929; +@onyx-groupbox-text-color: white; +@onyx-picker-text-color: black; +@onyx-popup-text-color: white; +@onyx-progressbutton-text-color: #F1F1F1; +@onyx-radiobutton-active-text-color: white; +@onyx-text-color: #333333; +@onyx-togglebutton-text-color: white; +@onyx-toolbar-button-text-color: #F2F2F2; +@onyx-toolbar-input-focus-text-color: #000; +@onyx-toolbar-input-placeholder-text-color: #ddd; +@onyx-toolbar-input-text-color: #e5e5e5; +@onyx-toolbar-text-color: white; +@onyx-tooltip-text-color: white; + +/* Background Colors */ +/* ---------------------------------------*/ +@onyx-background: #EAEAEA; +@onyx-light-background: #CACACA; +@onyx-dark-background: #555656; +@onyx-selected-background: #C4E3FE; + +@onyx-button-background: #E1E1E1; +@onyx-groupbox-background: #4C4C4C; +@onyx-highlight-background: #DEDFDF; +@onyx-input-background: transparent; +@onyx-input-focused-background: white; +@onyx-menu-item-hover: #284152; +@onyx-picker-background: #E1E1E1; +@onyx-picker-item-background: #cde7fe; +@onyx-popup-background: #4C4C4C; +@onyx-progressbar-background: #B8B8B8; +@onyx-progressbar-bar-background: #58ABEF; +@onyx-radiobutton-active-background: #0091F2; +@onyx-radiobutton-background: #E7E7E7; +@onyx-scrim-background: black; +@onyx-scrim-opacity: 0.65; +@onyx-switeable-item-background: #EAEAEA; +@onyx-togglebutton-background: #8BBA3D; +@onyx-togglebutton-knob-background: #F6F6F6; +@onyx-togglebutton-off-background: #B1B1B1; +@onyx-toolbar-background: #4C4C4C; +@onyx-toolbar-button-background: #555656; +@onyx-toolbar-input-background: rgba(0, 0, 0, 0.1); +@onyx-toolbar-input-focused-background: white; +@onyx-tooltip-background: #216593; + +/* Border Radius */ +/* ---------------------------------------*/ +@onyx-border-radius: 4px; +@onyx-border-radius-tight: 3px; + +@onyx-button-border-radius: @onyx-border-radius-tight; +@onyx-groupbox-border-radius: @onyx-border-radius; +@onyx-input-border-radius: @onyx-border-radius-tight; +@onyx-menu-border-radius: @onyx-border-radius-tight; +@onyx-progressbar-border-radius: @onyx-border-radius-tight; +@onyx-radiobutton-border-radius: @onyx-border-radius-tight; +@onyx-togglebutton-border-radius: @onyx-border-radius-tight; +@onyx-tooltip-border-radius: @onyx-border-radius-tight; + +/* Padding */ +/* ---------------------------------------*/ +@onyx-button-padding-lr: 18px; +@onyx-button-padding-tb: 6px; +@onyx-tabbutton-padding-lr: 34px; +@onyx-tabbutton-padding-tb: 8px; + +/* Icon Sizes */ +/* ---------------------------------------*/ +@onyx-icon-size: 32px; + +/* Disabled Opacity */ +/* ---------------------------------------*/ +@onyx-disabled-opacity: 0.4; + +/* Gradient Overlays */ +/* ---------------------------------------*/ +@onyx-gradient: url(../images/gradient.png); +@onyx-gradient-invert: url(../images/gradient-invert.png); + +@onyx-button-active-gradient: @onyx-gradient-invert; +@onyx-button-gradient: @onyx-gradient; +@onyx-groupbox-gradient: @onyx-gradient; +@onyx-popup-gradient: @onyx-gradient; +@onyx-progressbar-bar-gradient: @onyx-gradient; +@onyx-progressbar-gradient: @onyx-gradient-invert; +@onyx-radiobutton-active-gradient: @onyx-gradient-invert; +@onyx-radiobutton-gradient: @onyx-gradient; +@onyx-togglebutton-gradient: @onyx-gradient-invert; +@onyx-togglebutton-knob-gradient: @onyx-gradient; +@onyx-toolbar-gradient: @onyx-gradient; +@onyx-tooltip-gradient: @onyx-gradient; + +/* Images */ +/* ---------------------------------------*/ +@onyx-checkbox-image: url(../images/checkbox.png); +@onyx-checkbox-image-height: 32px; +@onyx-checkbox-image-width: 32px; + +@onyx-grabber-image: url(../images/grabbutton.png); +@onyx-grabber-image-height: 27px; +@onyx-grabber-image-width: 23px; + +@onyx-more-toolbar-button-image: url(../images/more.png); +@onyx-more-toolbar-button-image-height: 32px; +@onyx-more-toolbar-button-image-width: 32px; + +@onyx-slider-knob-image: url(../images/slider-handle.png); +@onyx-slider-knob-image-height: 40px; +@onyx-slider-knob-image-width: 40px; + +@onyx-spinner-dark-image: url(../images/spinner-dark.gif); +@onyx-spinner-light-image: url(../images/spinner-light.gif); +@onyx-spinner-image-width: 59px; +@onyx-spinner-image-height: 58px; diff --git a/lib/onyx/css/onyx.css b/lib/onyx/css/onyx.css new file mode 100644 index 0000000..c2b3519 --- /dev/null +++ b/lib/onyx/css/onyx.css @@ -0,0 +1,1153 @@ +/* WARNING: This is a generated file for backward-compatibility. Most */ +/* usrs should instead modify LESS files. If you choose to edit this CSS */ +/* directly rather than LESS files, you should make sure less.xx.yy.min.js */ +/* is commented out in your debug.html, and run deploy.sh/bat using the */ +/* '-c' flag to disable LESS compilation. This will force the loader and */ +/* minifier to fall back to using CSS files in place of the same-name */ +/* LESS file. */ + +/* Onyx default parameters defined here */ +/* Fonts */ +/* ---------------------------------------*/ +/* Text Colors */ +/* ---------------------------------------*/ +/* Background Colors */ +/* ---------------------------------------*/ +/* Border Radius */ +/* ---------------------------------------*/ +/* Padding */ +/* ---------------------------------------*/ +/* Icon Sizes */ +/* ---------------------------------------*/ +/* Disabled Opacity */ +/* ---------------------------------------*/ +/* Gradient Overlays */ +/* ---------------------------------------*/ +/* Images */ +/* ---------------------------------------*/ +/* Onyx rules defined here */ +/* onyx-classes.less - combined CSS (less) files for all released Onyx controls + into single onyx.less file to avoid IE bug that allows + a maximum of 31 style sheets to be loaded before silently failing */ +.onyx { + color: #333333; + font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; + font-size: 20px; + cursor: default; + background-color: #eaeaea; + /* remove automatic tap highlight color */ + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +/* prevent IE from inheriting line-height for these elements */ +.onyx button, +.onyx label, +.onyx input { + line-height: normal; +} +.onyx-selected { + background-color: #c4e3fe; +} +/* LESS pre-calculations */ +/* Individual Widget CSS */ +/* Icon.css */ +.onyx-icon, +.onyx-icon-toggle { + width: 32px; + height: 32px; + background-repeat: no-repeat; + display: inline-block; + vertical-align: middle; +} +.onyx-icon.onyx-icon-button.active, +.onyx-icon.onyx-icon-button.pressed, +.onyx-icon.onyx-icon-button:active:hover, +.onyx-icon-toggle.active { + background-position: 0 -32px; +} +.onyx-icon.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-icon.disabled:active:hover { + background-position: 0 0px; +} +/* Button.css */ +.onyx-button { + outline: 0; + color: #292929; + font-size: 16px; + text-align: center; + white-space: nowrap; + margin: 0; + padding: 6px 18px; + overflow: hidden; + border-radius: 3px; + /* for IE8 */ + + border: 1px solid #707070; + border: 1px solid rgba(15, 15, 15, 0.2); + /* + The border and the gradient interact in a strange way that + causes the bottom-border (top if the gradient is aligned top) + to be lighter than other borders. + We can fix it by using the darker bottom border below, but + then there are a few rogue pixels that end up very dark. + */ + + /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ + + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); + background: #e1e1e1 url(./../images/gradient.png) repeat-x bottom; + background-size: contain; + /**/ + + text-overflow: ellipsis; + /* the following cause arcane problems on IE */ + + /* + min-width: 14px; + min-height: 20px; + */ + +} +/* + IE8 can't handle these selectors in tandem: + .onyx-button.active, .onyx-button:active:not([disabled]) { + + the effect is as if .onyx-button.active doesn't exist +*/ +.onyx-button.active, +.onyx-button.pressed { + background-image: url(./../images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button:active:hover:not([disabled]) { + background-image: url(./../images/gradient-invert.png); + background-position: top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); +} +.onyx-button[disabled] { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-button > img { + padding: 0px 3px; +} +/* Remove the focused inner-border style in Firefox (Windows) */ +.onyx-button::-moz-focus-inner { + border: 0; +} +/* Checkbox.css */ +.onyx-checkbox { + cursor: pointer; + height: 32px; + width: 32px; + background: url(./../images/checkbox.png) no-repeat; + /* reset for ? */ + + margin: 0px; + /* these entries cause toggle-button and checkbox to line up properly*/ + + display: inline-block; + vertical-align: middle; +} +.onyx-checkbox[checked] { + background-position: 0px -32px; +} +.onyx-checkbox[disabled] { + opacity: 0.4; +} +/* Grabber.css */ +.onyx-grabber { + background: url(./../images/grabbutton.png) no-repeat center; + width: 23px; + height: 27px; +} +/* Popup.css */ +.onyx-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c url(./../images/gradient.png) repeat-x 0 bottom; +} +.onyx-popup-decorator { + position: relative; +} +/* Groupbox.css */ +.onyx-groupbox > * { + display: block; + /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ + + border-color: #aaaaaa; + border-style: solid; + border-width: 0 1px 1px 1px; + /*padding: 10px;*/ + + /* reset styles that make 'item' look bad if they happen to be there */ + + border-radius: 0; + margin: 0; + font-size: 16px; +} +.onyx-groupbox > *:first-child { + border-top-color: #aaaaaa; + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > *:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > *:first-child:last-child { + border-radius: 4px; +} +.onyx-groupbox-header { + padding: 2px 10px; + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; + /**/ + + background-color: #4c4c4c; + border: none; + background: #4c4c4c url(./../images/gradient.png) repeat-x 0 10px; +} +.onyx-groupbox .onyx-input-decorator { + display: block; +} +.onyx-groupbox > .onyx-input-decorator { + border-color: #aaaaaa; + border-width: 0 1px 1px 1px; + border-radius: 0; +} +.onyx-groupbox > .onyx-input-decorator:first-child { + border-width: 1px; + border-radius: 4px 4px 0 0; +} +.onyx-groupbox > .onyx-input-decorator:last-child { + border-radius: 0 0 4px 4px; +} +.onyx-groupbox > .onyx-input-decorator:first-child:last-child { + border-radius: 4px; +} +/* Input.css */ +.onyx-input-decorator { + padding: 6px 8px 10px 8px; + border-radius: 3px; + border: 1px solid; + border-color: rgba(0, 0, 0, 0.1); + margin: 0; +} +.onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + border-color: rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-input-decorator.onyx-disabled { + /* FIXME: needed to color a disabled input placeholder. */ + + /*-webkit-text-fill-color: #888;*/ + + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-input-decorator > input { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > input { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > input { + cursor: default; +} +/* Menu.css */ +.onyx-menu, +.onyx.onyx-menu { + min-width: 160px; + top: 100%; + left: 0; + margin-top: 2px; + padding: 3px 0; + border-radius: 3px; +} +.onyx-menu.onyx-menu-up { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 2px; +} +.onyx-toolbar .onyx-menu { + margin-top: 11px; + border-radius: 0 0 3px 3px; +} +.onyx-toolbar .onyx-menu.onyx-menu-up { + margin-top: 0; + margin-bottom: 10px; + border-radius: 3px 3px 0 0; +} +.onyx-menu-item { + display: block; + padding: 10px; +} +.onyx-menu-item:hover { + background: #284152; +} +.onyx-menu-divider, +.onyx-menu-divider:hover { + margin: 6px 0; + padding: 0; + border-bottom: 1px solid #aaa; +} +.onyx-menu-label { + cursor: default; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-menu-label:hover { + background: none; +} +/* customize a toolbar to support menus */ +.onyx-menu-toolbar, +.onyx-toolbar.onyx-menu-toolbar { + position: relative; + z-index: 10; + overflow: visible; +} +/* Picker.css */ +.onyx-picker-decorator .onyx-button { + padding: 10px 18px; +} +.onyx-picker { + top: 0; + margin-top: -3px; + min-width: 0; + width: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + color: black; + background: #e1e1e1; +} +.onyx-picker.onyx-menu-up { + top: auto; + bottom: 0; + margin-top: 3px; + margin-bottom: -3px; +} +.onyx-picker .onyx-menu-item { + text-align: center; +} +.onyx-picker .onyx-menu-item:hover { + background-color: transparent; +} +.onyx-picker .onyx-menu-item.selected, +.onyx-picker .onyx-menu-item.active, +.onyx-picker .onyx-menu-item:active:hover { + border-top: 1px solid rgba(0, 0, 0, 0.1); + background-color: #cde7fe; + box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); +} +.onyx-picker .onyx-menu-item { + border-top: 1px solid rgba(255, 255, 255, 0.5); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, +.onyx-flyweight-picker :first-child > .onyx-menu-item { + border-top: none; +} +.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, +.onyx-flyweight-picker :last-child > .onyx-menu-item { + border-bottom: none; +} +/* TextArea.css */ +.onyx-input-decorator > textarea { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + box-shadow: none; + /* Remove scrollbars and resize handle */ + + resize: none; + overflow: auto; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > textarea { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > textarea { + cursor: default; +} +.onyx-textarea { + /* need >=50px for scrollbar to be usable on mac */ + + min-height: 50px; +} +/* RichText.css */ +.onyx-input-decorator > .onyx-richtext { + /* reset */ + + margin: 0; + padding: 0; + border: none; + outline: none; + cursor: pointer; + background-color: transparent; + background-image: none; + font-size: 16px; + min-height: 20px; + min-width: 100px; + box-shadow: none; + /* FIXME: hack for styling reset on Android */ + + /* -webkit-appearance: caret;*/ + +} +.onyx-input-decorator.onyx-focused > .onyx-richtext { + cursor: text; +} +.onyx-input-decorator.onyx-disabled > .onyx-richtext { + cursor: default; +} +/* RadioButton.css */ +.onyx-radiobutton { + padding: 8px 12px; + margin: 0; + outline: 0; + font-size: 16px; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + text-align: center; + /**/ + + background: #e7e7e7 url(./../images/gradient.png) repeat-x bottom; + /* IE8 */ + + border: 1px solid #333333; + border: 1px solid rgba(15, 15, 15, 0.2); + /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ + + border-right-color: rgba(0, 0, 0, 0); + box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); +} +.onyx-radiobutton:first-child { + border-radius: 3px 0 0 3px; +} +.onyx-radiobutton:last-child { + border-radius: 0px 3px 3px 0px; + /* IE8 */ + + border-right: 1px solid #333333; + border-right: 1px solid rgba(15, 15, 15, 0.2); +} +.onyx-radiobutton.active { + color: #ffffff; + background: #0091f2 url(./../images/gradient-invert.png) repeat-x top; + border-top: 1px solid rgba(15, 15, 15, 0.6); + box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); +} +/* Scrim.css */ +.onyx-scrim { + z-index: 1; + /* + note: by using pointer-events we allow tapping on scrim + while it is fading out; however, this requires any showing classes + to set pointer events to auto or scrim will not function as expected. + */ + + pointer-events: none; +} +.onyx-scrim.onyx-scrim-translucent { + pointer-events: auto; + background-color: #000000; + opacity: 0.65; + filter: alpha(opacity=65); +} +.onyx-scrim.onyx-scrim-transparent { + pointer-events: auto; + background: transparent; +} +/* TabButton.css */ +.onyx-radiobutton.onyx-tabbutton { + padding: 8px 34px; + font-size: 20px; + border-radius: 0px; +} +/* ToggleButton.css */ +.onyx-toggle-button { + display: inline-block; + height: 32px; + line-height: 32px; + min-width: 64px; + vertical-align: middle; + text-align: center; + /* */ + + border-radius: 3px; + box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); + background: #8bba3d url(./../images/gradient-invert.png) repeat-x bottom; + background-size: auto 100%; + /* label */ + + color: #ffffff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; +} +.onyx-toggle-button.off { + background-color: #b1b1b1 !important; +} +.onyx-toggle-button-knob { + display: inline-block; + width: 30px; + height: 30px; + margin: 1px; + border-radius: 3px; + background: #f6f6f6 url(./../images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-toggle-button .onyx-toggle-button-knob { + box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: right; +} +.onyx-toggle-button.off .onyx-toggle-button-knob { + box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); + float: left; +} +.onyx-toggle-button.disabled, +.onyx-icon-button.disabled { + opacity: 0.4; + filter: alpha(opacity=40); +} +.onyx-toggle-content { + min-width: 32px; + padding: 0 6px; +} +.onyx-toggle-content.empty { + padding: 0; +} +.onyx-toggle-content.off { + float: right; +} +.onyx-toggle-content.on { + float: left; +} +/* Toolbar.css */ +.onyx-toolbar { + /* + line-height is unreliable for centering, instead + use vertical-align: middle to align + elements along a common centerline and use + padding to fill out the space. + */ + + padding: 9px 8px 10px 8px; + border: 1px solid #3A3A3A; + background: #4c4c4c url(./../images/gradient.png) repeat-x 0 bottom; + background-size: contain; + color: #ffffff; + /**/ + + white-space: nowrap; + overflow-y: visible; + font-size: 20px; +} +.onyx-toolbar-inline > *, +.enyo-fittable-columns-layout.onyx-toolbar-inline > * { + display: inline-block; + vertical-align: middle; + margin: 4px 6px 5px; + box-sizing: border-box; +} +.onyx-toolbar .onyx-icon-button { + margin: 3px 2px 1px; +} +.onyx-toolbar .onyx-button { + color: #f2f2f2; + background-color: #555656; + border-color: rgba(15, 15, 15, 0.5); + margin-top: 0; + margin-bottom: 0; + height: 50px; +} +.onyx-toolbar .onyx-input-decorator { + margin: 1px 3px; + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); + padding: 0px 6px 5px 6px; +} +.onyx-toolbar .onyx-input-decorator.onyx-focused { + box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); + background-color: #ffffff; +} +.onyx-toolbar .onyx-input-decorator .onyx-input { + color: #e5e5e5; + font-size: 14px; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus { + color: #000000; +} +.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { + color: #dddddd; +} +/* Tooltip.css */ +.onyx-tooltip { + z-index: 20; + left: 0; + padding: 4px 6px; + margin-top: 4px; + margin-left: -6px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + color: #ffffff; + background: #216593 url(./../images/gradient.png) repeat-x 0 bottom; + border-radius: 3px; + white-space: nowrap; +} +/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ +.onyx-tooltip.right-arrow { + left: 30px; +} +/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ +.onyx-tooltip::before { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + left: 16px; +} +.onyx-tooltip::after { + content: ''; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + position: absolute; + top: -6px; + margin-left: -12px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ +.onyx-tooltip.below { + top: 100%; +} +.onyx-tooltip.below.right-arrow::after { + border-bottom: 6px solid #1D587F; + top: -6px; +} +.onyx-tooltip.below.left-arrow::before { + border-bottom: 6px solid #1D587F; + top: -6px; +} +/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ +.onyx-tooltip.above { + top: -100%; +} +.onyx-tooltip.above.right-arrow::after { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +.onyx-tooltip.above.left-arrow::before { + content: ''; + border-top: 6px solid #1D587F; + top: 100%; +} +/* ProgressBar.css */ +.onyx-progress-bar { + margin: 8px; + height: 8px; + border: 1px solid rgba(15, 15, 15, 0.2); + border-radius: 3px; + background: #b8b8b8 url(./../images/gradient-invert.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar { + height: 100%; + border-radius: 3px; + background: #58abef url(./../images/gradient.png) repeat-x; + background-size: auto 100%; +} +.onyx-progress-bar-bar.striped { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.onyx-progress-bar-bar.striped.animated { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +/* ProgressButton.css */ +.onyx-progress-button { + position: relative; + height: 36px; + line-height: 36px; + color: #f1f1f1; + font-size: 16px; + text-overflow: ellipsis; +} +.onyx-progress-button-bar { + height: 36px; +} +.onyx-progress-button-icon { + display: inline-block; + position: absolute; + top: 2px; + right: 0; +} +.onyx-progress-button-client { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 36px; + margin-left: 8px; +} +.onyx-progress-button-client > * { + display: inline-block; +} +/* Slider.css */ +.onyx-slider { + position: relative; + margin: 8px 20px; +} +.onyx-slider-taparea { + position: absolute; + top: -11px; + height: 28px; + width: 100%; +} +.onyx-slider-knob { + position: relative; + height: 40px; + width: 40px; + background: url(./../images/slider-handle.png) left top no-repeat; + margin: -23px -20px; +} +.onyx-slider-knob.active, +.onyx-slider-knob.pressed, +.onyx-slider-knob:active:hover { + background-position: 0 -40px; +} +/* RangeSlider.css */ +.onyx-range-slider-knob { + top: -17px; +} +.onyx-range-slider-label { + position: relative; + top: -18px; + text-align: center; + white-space: nowrap; +} +/* Item.css */ +.onyx-item { + padding: 14px; +} +.onyx-highlight, +.onyx-highlight.onyx-swipeable-item-content { + background-color: #dedfdf; +} +.enyo-selected, +.enyo-selected.onyx-swipeable-item-content { + background-color: #c4e3fe; +} +.onyx-item.onyx-swipeable-item { + overflow: hidden; + padding: 0; +} +.onyx-swipeable-item-content { + background-color: #eaeaea; + box-sizing: border-box; + padding: 18px 6px; + min-height: 40px; +} +/* Spinner.css */ +.onyx-spinner { + width: 59px; + height: 58px; + display: inline-block; + background: url(./../images/spinner-dark.gif) no-repeat 0 0; +} +.onyx-spinner.onyx-light { + background: url(./../images/spinner-light.gif) no-repeat 0 0; +} +/* MoreToolbar.css */ +.onyx-more-toolbar { + overflow: visible; + position: relative; + z-index: 10; +} +.onyx-more-toolbar.active { + z-index: 11; +} +.onyx-more-menu { + left: auto; + right: 0px; + min-width: 0; +} +.onyx-more-toolbar .onyx-more-menu > * { + float: right; + clear: both; + margin: 5px; + margin-top: 5px; + margin-bottom: 5px; +} +.onyx-more-button { + background-image: url(./../images/more.png); + width: 32px; + height: 32px; +} +/* DatePicker.css */ +.onyx-datepicker-month { + min-width: 75px; +} +.onyx-datepicker-day { + min-width: 60px; +} +.onyx-datepicker-year { + min-width: 70px; +} +/* TimePicker.css */ +.onyx-timepicker-hour { + min-width: 60px; +} +.onyx-timepicker-minute { + min-width: 60px; +} +.onyx-timepicker-ampm { + min-width: 60px; +} +/* ButtonColors.css */ +.onyx-button.onyx-blue { + background-color: #35A8EE; + color: #F2F2F2; +} +.onyx-button.onyx-affirmative { + background-color: #91BA07; + color: #F2F2F2; +} +.onyx-button.onyx-negative { + background-color: #C51616; + color: #F2F2F2; +} +.onyx-button.onyx-dark { + background-color: #555656; + color: #F2F2F2; +} +.onyx-button.onyx-light { + background-color: #cacaca; + color: #2F2F2F; +} +/* ContextualPopup.css */ +.onyx-contextual-popup-title { + font-weight: bold; + padding: 24px 32px 0px; +} +.onyx-contextual-popup-scroller { + padding: 24px 32px; +} +.onyx-contextual-popup-action-buttons { + display: inline-block; + width: 100%; + text-align: center; +} +.onyx-contextual-popup-action-button { + margin-left: 5px; + margin-right: 5px; +} +.onyx-contextual-popup, +.onyx.onyx-contextual-popup { + font-size: 16px; + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 6px; + color: #ffffff; + background: #4c4c4c; +} +/*setup the nub*/ +.onyx-contextual-popup::after { + content: ''; + position: absolute; + top: -10px; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; +} +/*for popups above activator*/ +.onyx-contextual-popup.vertical.above { + top: auto; + margin-top: -10px; + bottom: 100%; + margin-bottom: 10px; +} +/*for popups below activator*/ +.onyx-contextual-popup.vertical.below { + margin-top: 10px; +} +/*for popups on the left of the activator*/ +.onyx-contextual-popup.right.horizontal { + margin-left: -11px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.left.horizontal { + margin-left: 10px; +} +/*nub positioning*/ +/*horizontally centered nub*/ +.onyx-contextual-popup.vertical::after { + position: absolute; + left: 45%; + border-bottom: 10px solid #4c4c4c; + border-top: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +/*nub near horizontal left*/ +.onyx-contextual-popup.vertical.right::after { + left: 0%; + margin-left: 20px; +} +/*nub near horizontal right*/ +.onyx-contextual-popup.vertical.left::after { + left: 100%; + margin-left: -55px; +} +/*downward facing nub*/ +.onyx-contextual-popup.vertical.above::after { + top: 100%; + border-top: 10px solid #4c4c4c; + border-bottom: none; + border-left: 10px solid transparent; + border-right: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right::after { + top: 0%; + margin-top: -10px; + border-bottom: 10px solid #4c4c4c; + border-left: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.left::after { + top: 0%; + margin-top: -10px; + border-right: 10px solid transparent; +} +/*nub positioning for left/right popups*/ +/*vertically centered nub for popups on left of activator*/ +.onyx-contextual-popup.right::after { + left: 100%; + top: 47%; + margin-right: 20px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on left of activator*/ +.onyx-contextual-popup.right.high::after { + top: 35px; + border-left: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on left of activator*/ +.onyx-contextual-popup.right.low::after { + top: 100%; + margin-top: -55px; + border-left: 10px solid #4C4C4C; +} +/*vertically centered nub for popups on right of activator*/ +.onyx-contextual-popup.left::after { + left: 0%; + margin-left: -20px; + top: 45%; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical top for popups on right of activator*/ +.onyx-contextual-popup.left.high::after { + top: 35px; + border-right: 10px solid #4C4C4C; +} +/*nub near vertical bottom for popups on right of activator*/ +.onyx-contextual-popup.left.low::after { + top: 100%; + margin-top: -55px; + border-right: 10px solid #4C4C4C; +} +/*corners*/ +/*vertical top corners*/ +/*for popups on the left of the activator*/ +.onyx-contextual-popup.vertical.right.corner { + margin-left: 0px; +} +/*for popups on the right of the activator*/ +.onyx-contextual-popup.vertical.left.corner { + margin-left: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.vertical.below.right.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.vertical.below.left.corner::after { + top: 0%; + left: 100%; + margin-top: -10px; + margin-left: -19px; + border-right: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +.onyx-contextual-popup.vertical.below.right.corner::after { + top: 0%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-top: 10px solid transparent; +} +/*vertical bottom corners*/ +.onyx-contextual-popup.left.above.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.right.above.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.vertical.left.above.corner::after { + top: 100%; + margin-left: -19px; + border-right: 10px solid #4C4C4C; + border-bottom: 10px solid transparent; + border-top: none; +} +.onyx-contextual-popup.vertical.right.above.corner::after { + top: 100%; + left: 0%; + margin-left: -1px; + border-left: 10px solid #4c4c4c; + border-bottom: 10px solid transparent; + border-top: none; +} +/*horizontal bottom corners*/ +.onyx-contextual-popup.left.low.corner { + border-bottom-left-radius: 0px; +} +.onyx-contextual-popup.right.low.corner { + border-bottom-right-radius: 0px; +} +.onyx-contextual-popup.left.low.corner::after { + top: 100%; + left: 0%; + margin-top: -19px; + margin-left: -12px; + border-bottom: 10px solid #4c4c4c; + border-right: 10px solid #4c4c4c; +} +.onyx-contextual-popup.right.low.corner::after { + top: 100%; + left: 100%; + margin-top: -19px; + border-bottom: 10px solid#4c4c4c; + border-left: none; +} +/*horizontal top corners*/ +.onyx-contextual-popup.left.high.corner { + border-top-left-radius: 0px; +} +.onyx-contextual-popup.right.high.corner { + border-top-right-radius: 0px; +} +.onyx-contextual-popup.left.high.corner::after { + top: 0%; + left: 0%; + margin-top: -1px; + margin-left: -12px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +.onyx-contextual-popup.right.high.corner::after { + top: 0%; + left: 100%; + margin-top: -1px; + margin-left: -9px; + border-top: 10px solid #4C4C4C; + border-bottom: none; +} +/* some default colors */ +.onyx-dark { + background-color: #555656; +} +.onyx-light { + background-color: #cacaca; +} +.onyx-green { + background-color: #91BA07; +} +.onyx-red { + background-color: #C51616; +} +.onyx-blue { + background-color: #35A8EE; +} diff --git a/lib/onyx/css/onyx.less b/lib/onyx/css/onyx.less new file mode 100644 index 0000000..63cce3b --- /dev/null +++ b/lib/onyx/css/onyx.less @@ -0,0 +1,5 @@ +/* Onyx default parameters defined here */ +@import "onyx-variables.less"; + +/* Onyx rules defined here */ +@import "onyx-rules.less"; diff --git a/lib/onyx/css/package.js b/lib/onyx/css/package.js new file mode 100644 index 0000000..4cfd706 --- /dev/null +++ b/lib/onyx/css/package.js @@ -0,0 +1,3 @@ +enyo.depends( + "onyx.less" +); diff --git a/lib/onyx/deploy.bat b/lib/onyx/deploy.bat new file mode 100644 index 0000000..54dfbb1 --- /dev/null +++ b/lib/onyx/deploy.bat @@ -0,0 +1,32 @@ +@ECHO OFF + +REM make sure we don't stomp variables in calling script +SETLOCAL + +REM the location of this batch file +SET SOURCE="%~dp0" + +REM target location +SET TARGET=%1 + +IF [%TARGET%]==[] GOTO FAIL + +GOTO OK + +:FAIL + +ECHO Must supply target folder parameter, e.g.: +ECHO. +ECHO deploy.bat ../deploy/lib/onyx +ECHO. +GOTO :EOF + +:OK + +REM copy assets +XCOPY %SOURCE%images\*.* %TARGET%\images\ /Q /E + +REM copy root folder files +COPY %SOURCE%*.txt %TARGET%\ >NUL + +ENDLOCAL diff --git a/lib/onyx/deploy.sh b/lib/onyx/deploy.sh new file mode 100644 index 0000000..068d501 --- /dev/null +++ b/lib/onyx/deploy.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +SOURCE=$(cd `dirname $0`; pwd) + +# target location +TARGET=$1 + +if [ x$TARGET = x ]; then + +cat < + + + + controlled inline: onyx toolbar design + + + + + +

    + +

    + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + +
    + + +
    +
    Text in Div
    + +
    +
    +
    + +
    +
    +
    Text in Div
    + +
    +
    +
    + +
    +
    +
    +
    + +
    + + +
    +
    +
    Text in Div
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    Text in Div
    + +
    +
    +
    + +
    +
    +
    +
    + +
    + + +
    +
    +
    Text in Div
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    Text in Div
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    + +
    Text in Div
    + +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    Text in Div
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + diff --git a/lib/onyx/design/inline.html b/lib/onyx/design/inline.html new file mode 100644 index 0000000..47b593a --- /dev/null +++ b/lib/onyx/design/inline.html @@ -0,0 +1,103 @@ + + + + + inline: onyx toolbar design + + + + + +

    +
    + +
    +
    + + +
    Text
    +
    + + +
    +
    Text in Div
    +
    +
    + + +
    + +
    +
    + + +
    +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    +
    + + diff --git a/lib/onyx/design/menu-icon-bookmark.png b/lib/onyx/design/menu-icon-bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..81d23446edba49f7d4a60e0b04dae0ae5ae8718c GIT binary patch literal 1883 zcmV-h2c-CkP)o!!~4C?;@{e`j{)%=!QG{r96-mc^drP}vh6 z&jirKjiM<3DPv)K{~rYM3?JqNiTo}?XNfXIDO|HFh9ZwEa=n!7-@m_w=1k`!npXoM zSH!mv1WHCnNBQED9`n`!h1BCvfr57&@~TKAQcc&i$68#-grp{}3KQR@ac>pkhMakD z_wL=blarHOsZ{FQwzjsHpx>O-($dmIkX|6VLNvs$x~~6l`}XZm>0OBC1hBRz0{mHJ zZ*TACwY9a|=zeZ-ak0`10mCr(oZsYU!C=rw%-a76$|Jd0tgglC1b0>cNT;y$PLBEx)kY_ z{*za*BS(&C1S>m!{J22~xyBg~|5ld*owAZpoRSiifRY_Nc+lwS>3M*~>bknRREcTc zbqY?$rfCYuby9~##EnoVgPbSkSLyy|PA5*B7&&+D+&tzQIe2gc(#0gB6n1ZtMImOP-KTwqO1OeAU8 zN#yY1!>x2Jm1+VWP^v+dc*ftAA==d-GgfzZckkqD%+Aj0xss70Tm&T<|5-)!^2w7Y zcXV`gaLKsBzz}xP9CM8jHeR1z$HKG%%6Rc*qM9 z#BrZnB+FHCLFWlT9>rRwmkr1v(}yA=fP1wF1Pr+5vWh653ZAaM;E4;MJoW9l_WpOz z+H=pwRFxW3P0Dgi>V8c4ytvOk4gq`!%Rywi3S5Iyd7Y6`bPQL0C0(-Sp`IW@F;Bg< zQVJHiA%U@pCYY83 zc0ZUm5N!wr+0Nd#*vI*HLf&)=2!(+}45~;V5hdLYF*L`{{m^qccK#wSNHSU0RsfpY zku@tN6hyN!2Z~9ylXVk7lw2Xey^&}O&D>Ie0GqLBDQbuq)G&uyK-7h%T*7M(_{;Ed zeTAR3ezb+{X$`Ta&n|n%i!zOcPQSx;$U4*S`9deQjiIn=zzj)^rM>0eV}2 zjyASuTeWR`MUUtFtn|$n*bYiJ*;Bu;KA;klRN*SXDotf;Y3I%S;TKoPqLSXs5{7Mv zBY>OhSbL+6HGR^?THC7GD^P2tRADa*#XcBOd8MCK`_)J9u0{&pa12Ff7}wd0leREi zJtYWa<=~;_vH?5tS&t^IbWEdVyNCZ(j$&4ncYZek6sZpMS;ZwO!F(KRt;UX>b*3*D z0*XYr52MJ@&WzHBw8RG+XeH%u0!*WC6p1VDI4|%F#cs@Xz-Ie#-wl@h{+|7x7gI+2 z#wD0V-JixfPNtR{4=qPy`jFU4Lnc-6!T3MK&C~!&2L8*z4pm>yQuTAaKA1 zO~s9e>T;}NIX+C%pZRc{Eq*z|zQGCD25k z$%w0<{M{zjXzS3h*Nr1B>vE5%Ihs;FAxg|=ew0Cevk&tRaLq^aU2~EciVvYn-Xp+iGO^dT(vAoK1xpYpme|bDRp!idO0RR(9 V6nWnJ%Dn&p002ovPDHLkV1n6ngEIgC literal 0 HcmV?d00001 diff --git a/lib/onyx/design/toolbar-extended.html b/lib/onyx/design/toolbar-extended.html new file mode 100644 index 0000000..c90b47a --- /dev/null +++ b/lib/onyx/design/toolbar-extended.html @@ -0,0 +1,243 @@ + + + + + onyx toolbar design + + + + +
    + +
    +
    + +
    Text
    +
    + +
    +
    Text in Div
    +
    +
    + +
    + +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    Text in Div
    +
    +
    + +
    +
    +
    Text in Div
    +
    +
    + +
    +
    +
    +
    Text in Div
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    div
    + +
    +
    +
    +
    +
    div
    + +
    +
    +
    +
    +
    div
    + +
    +
    +
    +
    +
    div
    + +
    +
    +
    +
    +
    div
    + +
    +
    div
    + +
    +
    + +
    + +
    +
    +
    +
    div
    +
    +
    div
    + +
    +
    + +
    + +
    +
    +
    +
    div
    +
    +
    +
    +
    +
    div
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    div
    + +
    +
    div
    + +
    +
    + +
    + +
    +
    + + diff --git a/lib/onyx/design/toolbar.html b/lib/onyx/design/toolbar.html new file mode 100644 index 0000000..46bddf1 --- /dev/null +++ b/lib/onyx/design/toolbar.html @@ -0,0 +1,111 @@ + + + + + inline: onyx toolbar design + + + + + +

    +
    + +
    +
    + + +
    Text
    +
    + + +
    +
    Text in Div
    +
    +
    + + +
    + +
    +
    + + +
    +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    + + +
    +
    Text in Div
    + +
    +
    +
    +
    + + diff --git a/lib/onyx/images/checkbox.png b/lib/onyx/images/checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..9176591af4192b5f8fc9d1f66f77da078ae4ab5d GIT binary patch literal 5462 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 KMNUMnLSTZHmo(J? literal 0 HcmV?d00001 diff --git a/lib/onyx/images/gradient-invert.png b/lib/onyx/images/gradient-invert.png new file mode 100644 index 0000000000000000000000000000000000000000..44ab5ac084b0962fb8d709e84f158ec880744e6e GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<7!3HE7BzD~bQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F5`$3q|f;CtLC@59p8c`CQpH@h~YuU)o|cQ6aCV1LzC}Pgg&ebxsLQ0EN_9@c;k- literal 0 HcmV?d00001 diff --git a/lib/onyx/images/gradient.png b/lib/onyx/images/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..58562587c62b21c388f8957ad6e0370dba70487b GIT binary patch literal 255 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 literal 0 HcmV?d00001 diff --git a/lib/onyx/images/search-input-cancel.png b/lib/onyx/images/search-input-cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..8056b4a471e0a7da1e438c7d5cc9ef3a9862a813 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{doXXw8qoL zF~q|E?c{^J2NXD5_m;K2ySQ}j!6UXlF-xDC&r)DrS?=4Bc~t#_V$0s79`;Bj?UdzV zf`9U#f3RK_n!RCm*$wtn33t^i9UOLjW(ZBNST85=GK95iYsb&z55cF6Y%VEH4B)F$ z{>}P2g?$%Wa=;Qz<-^~%+VHnAEc;d8GBNA4$633pEE5f`_ypfX~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/lib/onyx/images/slider-handle.png b/lib/onyx/images/slider-handle.png new file mode 100644 index 0000000000000000000000000000000000000000..09e12fbd19e1ff9e3faef8f2a2baaffab78688ae GIT binary patch literal 3095 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 Pn1F;$An(;T&^-PCGf5vc literal 0 HcmV?d00001 diff --git a/lib/onyx/package.js b/lib/onyx/package.js new file mode 100644 index 0000000..b55d530 --- /dev/null +++ b/lib/onyx/package.js @@ -0,0 +1,4 @@ +enyo.depends( + "source", + "css" +); \ No newline at end of file diff --git a/lib/onyx/samples/ButtonGroupSample.html b/lib/onyx/samples/ButtonGroupSample.html new file mode 100644 index 0000000..e6c37a0 --- /dev/null +++ b/lib/onyx/samples/ButtonGroupSample.html @@ -0,0 +1,22 @@ + + + + + Button Group Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ButtonGroupSample.js b/lib/onyx/samples/ButtonGroupSample.js new file mode 100644 index 0000000..edce781 --- /dev/null +++ b/lib/onyx/samples/ButtonGroupSample.js @@ -0,0 +1,45 @@ +enyo.kind({ + name: "onyx.sample.ButtonGroupSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "RadioGroup"}, + {kind: "onyx.RadioGroup", onActivate:"radioActivated", components: [ + {content: "Alpha", active: true}, + {content: "Beta"}, + {content: "Gamma"} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "TabGroup"}, + {kind: "onyx.RadioGroup", onActivate:"tabActivated", controlClasses: "onyx-tabbutton", components: [ + {content: "Alpha", active: true}, + {content: "Beta"} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Button Group"}, + {kind: "Group", onActivate:"buttonActivated", classes: "onyx-sample-tools group", defaultKind: "onyx.Button", highlander: true, components: [ + {content: "Button A", active: true, classes: "onyx-affirmative"}, + {content: "Button B", classes: "onyx-negative"}, + {content: "Button C", classes: "onyx-blue"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} + ]} + ], + radioActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" radio button is selected."); + } + }, + tabActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" tab button is selected."); + } + }, + buttonActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" button is selected."); + } + } +}); diff --git a/lib/onyx/samples/ButtonSample.html b/lib/onyx/samples/ButtonSample.html new file mode 100644 index 0000000..832a0f4 --- /dev/null +++ b/lib/onyx/samples/ButtonSample.html @@ -0,0 +1,22 @@ + + + + + Button Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ButtonSample.js b/lib/onyx/samples/ButtonSample.js new file mode 100644 index 0000000..a038572 --- /dev/null +++ b/lib/onyx/samples/ButtonSample.js @@ -0,0 +1,46 @@ +enyo.kind({ + name: "onyx.sample.ButtonSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Buttons"}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.Button", content: "Button", ontap:"buttonTapped"} + ]}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.Button", content: "Affirmative", classes: "onyx-affirmative", ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Negative", classes: "onyx-negative", ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Blue", classes: "onyx-blue", ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Dark", classes: "onyx-dark", ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Custom", style: "background-color: purple; color: #F1F1F1;", ontap:"buttonTapped"} + ]}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.Button", content: "Active", classes: "active", ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Disabled", disabled: true, ontap:"buttonTapped"}, + {kind:"onyx.Button", content: "Active Disabled", classes: "active", disabled: true, ontap:"buttonTapped"} + ]}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.Button", content: "Tall Button", style: "height: 70px;", ontap:"buttonTapped"} + ]}, + {classes: "onyx-sample-divider", content: "Buttons with images"}, + {classes: "onyx-sample-tools", components: [ + {kind: "onyx.Button", name:"Image Button", ontap:"buttonTapped", components: [ + {tag: "img", attributes: {src: "assets/favicon.ico"}}, + {content: "There is an image here"} + ]}, + {kind: "onyx.Button", name:"Fishbowl Button", ontap:"buttonTapped", components: [ + {kind: "onyx.Icon", src: "assets/fish_bowl.png"} + ]} + ]}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} + ]} + ], + buttonTapped: function(inSender, inEvent) { + if (inSender.content){ + this.$.result.setContent("The \"" + inSender.getContent() + "\" button was tapped"); + } else { + this.$.result.setContent("The \"" + inSender.getName() + "\" button was tapped"); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/CheckboxSample.html b/lib/onyx/samples/CheckboxSample.html new file mode 100644 index 0000000..4f0e655 --- /dev/null +++ b/lib/onyx/samples/CheckboxSample.html @@ -0,0 +1,22 @@ + + + + + Checkbox Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/CheckboxSample.js b/lib/onyx/samples/CheckboxSample.js new file mode 100644 index 0000000..d2487e7 --- /dev/null +++ b/lib/onyx/samples/CheckboxSample.js @@ -0,0 +1,34 @@ +enyo.kind({ + name: "onyx.sample.CheckboxSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Checkboxes"}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.Checkbox", onchange:"checkboxChanged"}, + {kind:"onyx.Checkbox", onchange:"checkboxChanged"}, + {kind:"onyx.Checkbox", onchange:"checkboxChanged", checked: true} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Checkboxes Group"}, + {kind: "Group", classes: "onyx-sample-tools group", onActivate:"groupActivated", highlander: true, components: [ + {kind:"onyx.Checkbox", checked: true}, + {kind:"onyx.Checkbox"}, + {kind:"onyx.Checkbox"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} + ]} + ], + checkboxChanged: function(inSender, inEvent) { + this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); + }, + ordinals: ["1st", "2nd", "3rd"], + groupActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + var selected = inEvent.originator.indexInContainer(); + this.$.result.setContent("The " + this.ordinals[selected] + " checkbox in the group is selected."); + } + } +}); diff --git a/lib/onyx/samples/ContextualPopupSample.html b/lib/onyx/samples/ContextualPopupSample.html new file mode 100644 index 0000000..7bb8b0e --- /dev/null +++ b/lib/onyx/samples/ContextualPopupSample.html @@ -0,0 +1,23 @@ + + + + Contextual Popup Sample + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ContextualPopupSample.js b/lib/onyx/samples/ContextualPopupSample.js new file mode 100644 index 0000000..fd6131e --- /dev/null +++ b/lib/onyx/samples/ContextualPopupSample.js @@ -0,0 +1,240 @@ +enyo.kind({ + name: "onyx.sample.ContextualPopupSample", + kind: "FittableRows", + classes: "onyx enyo-fit", + handlers: { + ontap: "tapHandler" + }, + components: [ + {kind: "onyx.Toolbar", name:"topToolbar", classes: "onyx-menu-toolbar", style:"background-color:lightgray", components: [ + {kind:"FittableColumns", style:"width:100%;", components:[ + {kind: "onyx.MenuDecorator", components: [ + {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ContextualPopup", + title:"Toolbar Button", + floating:true, + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"test2"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"} + ] + } + ]}, + {kind: "onyx.MenuDecorator", fit:true, style:"position:absolute;right:0;", components: [ + {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ContextualPopup", + title:"Toolbar Button", + floating:true, + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"test2"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"}, + {content:"testing 3"}, + {content:"testing 4"}, + {content:"testing 5"}, + {content:"testing 6"} + ] + } + ]} + ]} + ]}, + {kind: "Scroller", fit: true, thumb:false, components:[ + {name:"buttonContainer", kind:"FittableRows", classes:"onyx-contextualpopup-button-container enyo-fit", components:[ + //Top row of buttons + {components:[ + {kind: "onyx.MenuDecorator", style:"display:inline-block", components: [ + {content: "Average"}, + {kind: "onyx.ContextualPopup", + title:"Average", + floating:true, + actionButtons:[ + {content:"Press Me"} + ], + components: [ + {content:"Item 1"}, + {content:"Item 2"}, + {content:"Item 3"}, + {content:"Item 4"}, + {content:"Item 5"} + ] + } + ]}, + + {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ + {content:"Small"}, + {kind: "onyx.ContextualPopup", + title:"Small", + floating:true + } + ]} + ]}, + //Center row of buttons + {fit:true, style:"padding-top:15%;padding-bottom:15%;", components:[ + {kind: "onyx.MenuDecorator", style:"display:inline-block;", components: [ + {content: "Wide"}, + {kind: "onyx.ContextualPopup", + style:"width:300px", + floating:true, + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"test2"} + ], + components: [ + {kind: "Scroller", style:"min-width:150px;", horizontal:"auto", touch:true, thumb:false, components:[ + {content:"testing 1"}, + {content:"testing 2"} + ]} + ] + } + ]}, + {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ + {content:"Long"}, + {kind: "onyx.ContextualPopup", + maxHeight: "200", + title:"Long", + floating:true, + actionButtons:[ + {content:"Press Me"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"}, + {content:"testing 3"}, + {content:"testing 4"}, + {content:"testing 5"}, + {content:"testing 6"}, + {content:"testing 7"}, + {content:"testing 9"}, + {content:"testing 10"}, + {content:"testing 11"}, + {content:"testing 12"}, + {content:"testing 13"}, + {content:"testing 14"}, + {content:"testing 15"}, + {content:"testing 16"}, + {content:"testing 17"}, + {content:"testing 18"}, + {content:"testing 19"}, + {content:"testing 20"}, + {content:"testing 21"}, + {content:"testing 22"}, + {content:"testing 23"}, + {content:"testing 24"}, + {content:"testing 25"}, + {content:"testing 26"}, + {content:"testing 27"}, + {content:"testing 28"}, + {content:"testing 29"}, + {content:"testing 30"} + ] + } + ]} + ]}, + //Bottom row of buttons + {components:[ + {kind: "onyx.MenuDecorator", style:"display:inline-block;", components: [ + {content: "Press Me"}, + {kind: "onyx.ContextualPopup", + title:"Press Me", + floating:true, + style:"width:200px", + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"test2"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"}, + {content:"testing 3"}, + {content:"testing 4"}, + {content:"testing 5"}, + {content:"testing 6"}, + {content:"testing 7"}, + {content:"testing 9"}, + {content:"testing 10"} + ] + } + ]}, + {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ + {content:"Try Me"}, + {kind: "onyx.ContextualPopup", + style:"width:250px", + title:"Try Me", + floating:true, + actionButtons:[ + {content:"Do Nothing", classes: "onyx-button-warning"}, + {content:"Dismiss", name:"dismiss_button"} + ], + components: [ + {content:"Item 1"}, + {content:"Item 2"}, + {content:"Item 3"}, + {content:"Item 4"}, + {content:"Item 5"} + ] + } + ]} + ]} + ]} + ]}, + {kind: "onyx.Toolbar", name:"bottomToolbar", classes: "onyx-menu-toolbar", style:"background-color:lightgray", components: [ + {kind:"FittableColumns", style:"width:100%;", components:[ + {kind: "onyx.MenuDecorator", components: [ + {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ContextualPopup", + title:"Toolbar Button", + floating:true, + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"test2"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"}, + {content:"testing 3"}, + {content:"testing 4"}, + {content:"testing 5"}, + {content:"testing 6"} + ] + } + ]}, + {kind: "onyx.MenuDecorator", fit:true, style:"position:absolute;right:0;", components: [ + {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ContextualPopup", name:"facebook", + title:"Toolbar Button", + floating:true, + actionButtons:[ + {content:"test1", classes: "onyx-button-warning"}, + {content:"Dismiss", name:"dismiss_button"} + ], + components: [ + {content:"testing 1"}, + {content:"testing 2"}, + {content:"testing 3"}, + {content:"testing 4"}, + {content:"testing 5"}, + {content:"testing 6"} + ] + } + ]} + ]} + ]} + ], + tapHandler: function(inSender, inEvent) { + if (inEvent.actionButton) { + enyo.log(inEvent.popup); //info about popup it's coming from + enyo.log("action button index: " + inEvent.originator.index); //index of action button + enyo.log("action button name: " + inEvent.originator.name); //name of action button (you can set this - see example use below) + + if (inEvent.originator.name == "dismiss_button"){ + inEvent.popup.hide(); + } + } + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/DatePickerSample.html b/lib/onyx/samples/DatePickerSample.html new file mode 100644 index 0000000..012f13f --- /dev/null +++ b/lib/onyx/samples/DatePickerSample.html @@ -0,0 +1,23 @@ + + + + + DatePicker Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/DatePickerSample.js b/lib/onyx/samples/DatePickerSample.js new file mode 100644 index 0000000..a5e0bfe --- /dev/null +++ b/lib/onyx/samples/DatePickerSample.js @@ -0,0 +1,108 @@ +enyo.kind({ + name: "onyx.sample.DatePickerSample", + kind: "FittableRows", + classes: "onyx", + handlers: { + onSelect: "updateDateValues" + }, + components: [ + {kind: "onyx.Toolbar", content:$L("Dates")}, + {kind: "FittableColumns", style: "padding: 10px", components:[ + {components: [ + {content:$L("Choose Locale:"), classes:"onyx-sample-divider"}, + {kind: "onyx.PickerDecorator", style:"padding:10px;", onSelect: "pickerHandler", components: [ + {content: "Pick One...", style: "width: 200px"}, + {kind: "onyx.Picker", components: [ + {content: 'en_us', active:true}, + {content: 'en_ca'}, + {content: 'en_ie'}, + {content: 'en_gb'}, + {content: 'en_mx'}, + {content: 'de_de'}, + {content: 'fr_fr'}, + {content: 'fr_ca'}, + {content: 'it_it'}, + {content: 'es_es'}, + {content: 'es_mx'}, + {content: 'es_us'} + ]} + ]} + ]} + ]}, + {kind:"onyx.Button",content:"Get Dates", style:"margin:10px;", ontap:"getDates"}, + {kind:"onyx.Button",content:"Reset Dates", ontap:"resetDates"}, + {style:"width:100%;height:5px;background-color:black;margin-bottom:5px;"}, + {caption: "Dates", style: "padding: 10px", components: [ + {content:"DATE",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"datePicker1", kind:"onyx.DatePicker"} + ]}, + {kind: "onyx.Groupbox", style:"padding:5px;", components: [ + {kind: "onyx.GroupboxHeader", content: "Value"}, + {name:"datePicker1Value", style:"padding:15px;"} + ]}, + {content:"DATE W/MIN & MAX YEARS",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"datePicker2", kind:"onyx.DatePicker", minYear:2010, maxYear:2020} + ]}, + {kind: "onyx.Groupbox", style:"padding:5px;", components: [ + {kind: "onyx.GroupboxHeader", content: "Value"}, + {name:"datePicker2Value", style:"padding:15px;"} + ]}, + {content:"DATE W/DAYS HIDDEN",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"datePicker3", kind:"onyx.DatePicker", dayHidden:true} + ]}, + {kind: "onyx.Groupbox", style:"padding:5px;", components: [ + {kind: "onyx.GroupboxHeader", content: "Value"}, + {name:"datePicker3Value", style:"padding:15px;"} + ]}, + {content:"DISABLED",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"datePicker4", kind:"onyx.DatePicker", disabled: true} + ]} + ]} + ], + initComponents: function() { + this.inherited(arguments); + this.locale = enyo.g11n.currentLocale().getLocale(); + }, + pickerHandler: function(inSender, inEvent){ + this.locale = inEvent.selected.content; + this.formatDate(); + return true; + }, + formatDate: function(){ + this.$.datePicker1.setLocale(this.locale); + this.$.datePicker2.setLocale(this.locale); + this.$.datePicker3.setLocale(this.locale); + this.$.datePicker4.setLocale(this.locale); + }, + resetDates: function(date) { + var d = new Date(); + this.$.datePicker1.setValue(d); + this.$.datePicker2.setValue(d); + this.$.datePicker3.setValue(d); + this.$.datePicker4.setValue(d); + this.getDates(); + }, + getDates: function(){ + var fmt = this.format(); + this.$.datePicker1Value.setContent(fmt.format(this.$.datePicker1.getValue())); + this.$.datePicker2Value.setContent(fmt.format(this.$.datePicker2.getValue())); + // reformat the formatter to display the Date wiht only Month and year + fmt = this.format('my'); + this.$.datePicker3Value.setContent(fmt.format(this.$.datePicker3.getValue())); + }, + updateDateValues: function(inSender, inEvent){ + var fmt = inEvent.name != "datePicker3" ? this.format() : this.format('my'); + this.$[inEvent.name + "Value"].setContent(fmt.format(inEvent.value)); + }, + format: function(dateComponents) { + return (fmt = new enyo.g11n.DateFmt({ + dateComponents: dateComponents || undefined, + date: 'short', + locale: new enyo.g11n.Locale(this.locale) + })); + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.css b/lib/onyx/samples/DrawerSample.css new file mode 100644 index 0000000..5d7684c --- /dev/null +++ b/lib/onyx/samples/DrawerSample.css @@ -0,0 +1,33 @@ +.drawer-sample { + padding: 10px; +} +.drawer-sample-divider { + color: #F49200; + text-transform: uppercase; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; + font-weight: bold; + margin-bottom: 8px; +} +.drawer-sample-label { + color: #1879CD; + font-size: 18px; + text-transform: uppercase; +} +.drawer-sample-box { + border: 2px solid lightblue; + padding: 4px; + white-space: nowrap; + overflow:hidden; +} +.drawer-sample-mtb { + margin-top: 3px; + margin-bottom: 3px; +} +.drawer-sample-mlr { + margin-left: 6px; + margin-right: 6px; +} +.drawer-sample-o { + border-color: orange; +} \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.html b/lib/onyx/samples/DrawerSample.html new file mode 100644 index 0000000..c713afa --- /dev/null +++ b/lib/onyx/samples/DrawerSample.html @@ -0,0 +1,22 @@ + + + + + Drawer Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.js b/lib/onyx/samples/DrawerSample.js new file mode 100644 index 0000000..299f9fa --- /dev/null +++ b/lib/onyx/samples/DrawerSample.js @@ -0,0 +1,41 @@ +enyo.kind({ + name: "onyx.sample.DrawerSample", + classes: "onyx drawer-sample", + components: [ + {content: "Drawers", classes:"drawer-sample-divider"}, + {content: "Activate (V)", classes: "drawer-sample-box drawer-sample-mtb", ontap:"activateDrawer"}, + {name: "drawer", kind: "onyx.Drawer", components: [ + {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"}, + {components: [ + {kind: "onyx.Checkbox", name: "animateSetting", value: true}, + {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"} + ]}, + {content: "Activate (V) (Toggled Animation)", classes: "drawer-sample-box drawer-sample-mtb", ontap:"activateDrawer2"}, + {name: "drawer2", kind: "onyx.Drawer", animated: true, components: [ + {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"} + ]}, + {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"} + ]}, + {content: "Foo
    Foo", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"}, + {kind: "FittableColumns", fit: true, ontap: "activateColumnsDrawer", classes: "drawer-sample-box drawer-sample-mtb drawer-sample-o", components: [ + {content: "Activate (H)", classes: "drawer-sample-box drawer-sample-mlr"}, + {name: "columnsDrawer", orient: "h", kind: "onyx.Drawer", open: false, components: [ + {content: "H-Drawer", classes: "drawer-sample-box drawer-sample-mlr"} + ]}, + {content: "Foo", fit: true, classes: "drawer-sample-box drawer-sample-mlr drawer-sample-o"}, + {content: "Foo", classes: "drawer-sample-box drawer-sample-mlr"} + ]}, + {content: "Foo", classes: "drawer-sample-box drawer-sample-mtb"} + ], + activateDrawer: function() { + this.$.drawer.setOpen(!this.$.drawer.open); + }, + activateDrawer2: function() { + this.$.drawer2.setAnimated(this.$.animateSetting.getValue()); + this.$.drawer2.setOpen(!this.$.drawer2.open); + }, + activateColumnsDrawer: function() { + this.$.columnsDrawer.setOpen(!this.$.columnsDrawer.open); + return true; + } +}); diff --git a/lib/onyx/samples/GroupboxSample.html b/lib/onyx/samples/GroupboxSample.html new file mode 100644 index 0000000..1822ca8 --- /dev/null +++ b/lib/onyx/samples/GroupboxSample.html @@ -0,0 +1,22 @@ + + + + + Groupbox Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/GroupboxSample.js b/lib/onyx/samples/GroupboxSample.js new file mode 100644 index 0000000..b47701d --- /dev/null +++ b/lib/onyx/samples/GroupboxSample.js @@ -0,0 +1,40 @@ +enyo.kind({ + name: "onyx.sample.GroupboxSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Groupboxes"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "Header"}, + {content: "I'm a group item!", style: "padding: 8px;"}, + {content: "I'm a group item!", style: "padding: 8px;"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", components: [ + {content: "I'm a group item!", style: "padding: 8px;"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "Header"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", style: "width: 100%", placeholder: "Enter text here"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", style: "width: 100%", value: "Middle"} + ]}, + {kind: "onyx.InputDecorator", style: "background: lightblue;", components: [ + {kind: "onyx.Input", style: "width: 100%;", value: "Last"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", style: "width: 100%", placeholder: "Enter text here"} + ]} + ]}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", type: "password", style: "width: 100%", placeholder: "Enter Password"} + ]} + ]} + ] +}); diff --git a/lib/onyx/samples/IconButtonSample.html b/lib/onyx/samples/IconButtonSample.html new file mode 100644 index 0000000..6c481ff --- /dev/null +++ b/lib/onyx/samples/IconButtonSample.html @@ -0,0 +1,22 @@ + + + + + IconButton Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/IconButtonSample.js b/lib/onyx/samples/IconButtonSample.js new file mode 100644 index 0000000..aa0c0c4 --- /dev/null +++ b/lib/onyx/samples/IconButtonSample.js @@ -0,0 +1,61 @@ +enyo.kind({ + name: "onyx.sample.IconButtonSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Icon"}, + {kind: "onyx.Icon", src: "assets/menu-icon-bookmark.png" }, + {tag: "br"}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Icon Button"}, + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png", disabled: true, ontap:"iconTapped"}, + {tag: "br"}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Grouped Icon Buttons"}, + {kind: "Group", onActivate:"iconGroupActivated", components: [ + {kind: "onyx.IconButton", active: true, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Toggle Icon Buttons"}, + {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", value: true, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", disabled: true, src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", value: true, disabled: true, src: "assets/menu-icon-bookmark.png"}, + {tag: "br"}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Icon Buttons in Toolbar"}, + {kind: "onyx.Toolbar", defaultKind: "onyx.IconButton", components: [ + {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, + {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, + {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, + {kind: "Control"}, + {kind: "Group", tag: null, onActivate:"iconGroupActivated", defaultKind: "onyx.IconButton", components: [ + {src: "assets/menu-icon-bookmark.png", active: true}, + {src: "assets/menu-icon-bookmark.png"}, + {src: "assets/menu-icon-bookmark.png"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} + ]} + ], + iconTappedCounts: {}, + iconTapped: function(inSender, inEvent) { + this.iconTappedCounts[inSender.name] = this.iconTappedCounts[inSender.name] || 0; + this.$.result.setContent("The icon button was tapped: " + (++this.iconTappedCounts[inSender.name])); + }, + toggleChanged: function(inSender, inEvent) { + this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); + }, + ordinals: ["1st", "2nd", "3rd"], + iconGroupActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + var selected = inEvent.originator.indexInContainer(); + this.$.result.setContent("The " + this.ordinals[selected] + " icon button in the group is selected."); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/InputSample.html b/lib/onyx/samples/InputSample.html new file mode 100644 index 0000000..5ee6303 --- /dev/null +++ b/lib/onyx/samples/InputSample.html @@ -0,0 +1,22 @@ + + + + + Input Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/InputSample.js b/lib/onyx/samples/InputSample.js new file mode 100644 index 0000000..21842bb --- /dev/null +++ b/lib/onyx/samples/InputSample.js @@ -0,0 +1,68 @@ +enyo.kind({ + name: "onyx.sample.InputSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Inputs"}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Enter text here", onchange:"inputChanged"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Search term", onchange:"inputChanged"}, + {kind: "Image", src: "assets/search-input-search.png"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", type:"password", placeholder: "Enter password", onchange:"inputChanged"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {content: "alwaysLookFocused:"}, + {kind: "onyx.Checkbox", onchange: "changeFocus"} + ]} + ]}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", disabled: true, value: "Disabled input"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {content: "Left:"}, + {kind: "onyx.Input", value: "Input Area", onchange:"inputChanged"}, + {content: " :Right"} + ]} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "RichTexts"}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.RichText", style: "width: 200px;", placeholder: "Enter text here", onchange:"inputChanged"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.RichText", style: "width: 200px;", placeholder: "Search term", onchange:"inputChanged"}, + {kind: "Image", src: "assets/search-input-search.png"} + ]} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "TextAreas"}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.TextArea", placeholder: "Enter text here", onchange:"inputChanged"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.TextArea", placeholder: "Search term", onchange:"inputChanged"}, + {kind: "Image", src: "assets/search-input-search.png"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No input entered yet."} + ]} + ], + inputChanged: function(inSender, inEvent) { + this.$.result.setContent("Input: " + inSender.getValue()); + }, + changeFocus: function(inSender, inEvent) { + this.$.inputDecorator.setAlwaysLooksFocused(inSender.getValue()); + this.$.inputDecorator2.setAlwaysLooksFocused(inSender.getValue()); + this.$.inputDecorator3.setAlwaysLooksFocused(inSender.getValue()); + } +}); diff --git a/lib/onyx/samples/MenuSample.html b/lib/onyx/samples/MenuSample.html new file mode 100644 index 0000000..ebd80af --- /dev/null +++ b/lib/onyx/samples/MenuSample.html @@ -0,0 +1,22 @@ + + + + + Menu Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/MenuSample.js b/lib/onyx/samples/MenuSample.js new file mode 100644 index 0000000..0d71c8a --- /dev/null +++ b/lib/onyx/samples/MenuSample.js @@ -0,0 +1,99 @@ +enyo.kind({ + name: "onyx.sample.MenuSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Menus in Toolbars"}, + {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ + {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]}, + {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ + {content: "Bookmarks menu"}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Menus from Buttons"}, + {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ + {content: "Popup menu (floating)"}, + {kind: "onyx.Menu", floating: true, components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "3"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ + {content: "Scrolling Popup menu"}, + {kind: "onyx.Menu", components: [ + {name: "menuScroller", kind: "enyo.Scroller", defaultKind: "onyx.MenuItem", vertical: "auto", classes: "enyo-unselectable", maxHeight: "200px", strategyKind: "TouchScrollStrategy", components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "3"}, + {content: "4"}, + {content: "5"}, + {classes: "onyx-menu-divider"}, + {content: "6"}, + {content: "7"} + ]} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ + {content: "Split Popup menu", kind: "onyx.Button", onActivate: "preventMenuActivate", style: "border-radius: 3px 0 0 3px;"}, + {content: "v", allowHtml:true, style: "border-radius: 0 3px 3px 0;"}, + {kind: "onyx.Menu", components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "3"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"menuSelection", classes:"onyx-sample-result", content:"No menu selection yet."} + ]} + ], + create: function() { + this.inherited(arguments); + }, + showPopup: function(inSender) { + var p = this.$[inSender.popup]; + if (p) { + p.show(); + } + }, + preventMenuActivate: function() { + return true; + }, + itemSelected: function(inSender, inEvent) { + //Menu items send an onSelect event with a reference to themselves & any directly displayed content + if (inEvent.originator.content){ + this.$.menuSelection.setContent(inEvent.originator.content + " Selected"); + } else if (inEvent.selected){ + // Since some of the menu items do not have directly displayed content (they are kinds with subcomponents), + // we have to handle those items differently here. + this.$.menuSelection.setContent(inEvent.selected.controlAtIndex(1).content + " Selected"); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/MoreToolbarSample.html b/lib/onyx/samples/MoreToolbarSample.html new file mode 100644 index 0000000..96e1730 --- /dev/null +++ b/lib/onyx/samples/MoreToolbarSample.html @@ -0,0 +1,22 @@ + + + + + MoreToolbar Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/MoreToolbarSample.js b/lib/onyx/samples/MoreToolbarSample.js new file mode 100644 index 0000000..14b1470 --- /dev/null +++ b/lib/onyx/samples/MoreToolbarSample.js @@ -0,0 +1,35 @@ +enyo.kind({ + name: "onyx.sample.MoreToolbarSample", + classes: "onyx onyx-sample", + kind: "FittableRows", + fit: true, + components: [ + {kind: "onyx.MoreToolbar", components: [ + {content: "More Toolbar", unmoveable: true}, + {kind: "onyx.Button", content: "Alpha"}, + {kind: "onyx.Button", content: "Beta"}, + {kind: "onyx.Button", content: "Gamma", unmoveable: true}, + {kind: "onyx.Button", content: "Epsilon"}, + {kind: "onyx.Button", content: "Othercon"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "pulez"} + ]}, + {kind: "onyx.Button", content: "Maxizon"} + ]}, + {fit: true, style: "background: lightpurple;padding:25px;", components: [ + {content: "The \"More Toolbar\" label and the Gamma button have the unmoveable property set to true."} + ]}, + {kind: "onyx.MoreToolbar", components: [ + {content: "More Toolbar", unmoveable: true}, + {kind: "onyx.Button", content: "Alpha"}, + {kind: "onyx.Button", content: "Beta"}, + {kind: "onyx.Button", content: "Gamma", unmoveable: true}, + {kind: "onyx.Button", content: "Epsilon"}, + {kind: "onyx.Button", content: "Othercon"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "pulez"} + ]}, + {kind: "onyx.Button", content: "Maxizon"} + ]} + ] +}); \ No newline at end of file diff --git a/lib/onyx/samples/PickerSample.html b/lib/onyx/samples/PickerSample.html new file mode 100644 index 0000000..7ca676f --- /dev/null +++ b/lib/onyx/samples/PickerSample.html @@ -0,0 +1,22 @@ + + + + + Picker Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/PickerSample.js b/lib/onyx/samples/PickerSample.js new file mode 100644 index 0000000..f9c4086 --- /dev/null +++ b/lib/onyx/samples/PickerSample.js @@ -0,0 +1,101 @@ +enyo.kind({ + name: "onyx.sample.PickerSample", + kind: "FittableRows", + classes: "onyx onyx-sample", + handlers: { + onSelect: "itemSelected" + }, + components: [ + {content: "Default Picker", classes:"onyx-sample-divider"}, + {kind: "onyx.PickerDecorator", components: [ + {}, + {kind: "onyx.Picker", components: [ + {content: "Gmail", active: true}, + {content: "Yahoo"}, + {content: "Outlook"}, + {content: "Hotmail"} + ]} + ]}, + {tag: "br"}, + {content: "Picker with Static Button", classes:"onyx-sample-divider"}, + {kind: "onyx.PickerDecorator", components: [ + {kind: "onyx.PickerButton", content: "Pick One...", style: "width: 200px"}, + {kind: "onyx.Picker", components: [ + {content: "Hello!"}, + {content: "I am busy."}, + {content: "Good Bye."} + ]} + ]}, + {tag: "br"}, + {content: "Integer Picker", classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.PickerDecorator", components: [ + {style: "min-width: 60px;"}, + {kind: "onyx.IntegerPicker", min: 0, max: 25, value: 5} + ]} + ]}, + {tag: "br"}, + {content: "Other Pickers", classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {content: "Date", classes: "onyx-sample-label"}, + {kind: "onyx.PickerDecorator", components: [ + {}, + {name: "monthPicker", kind: "onyx.Picker"} + ]}, + {kind: "onyx.PickerDecorator", components: [ + {style: "min-width: 60px;"}, + {name: "dayPicker", kind: "onyx.Picker"} + ]}, + {classes: "onyx-toolbar-inline", style:"margin: 0px;", components: [ + {content: "Year", classes: "onyx-sample-label"}, + {kind: "onyx.PickerDecorator", components: [ + {name:"yearPickerButton", style: "min-width: 80px;"}, + {name: "yearPicker", kind: "onyx.FlyweightPicker", count: 200, onSetupItem: "setupYear", components: [ + {name: "year"} + ]} + ]} + ]} + ]}, + {tag: "br"}, + {classes: "onyx-toolbar-inline", components: [ + {kind: "onyx.PickerDecorator", components: [ + {}, + {kind: "onyx.Picker", components: [ + {content: "Gmail"}, + {content: "Yahoo"}, + {content: "Outlook"}, + {content: "Hotmail", active: true} + ]} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Selection"}, + {name:"pickerSelection", classes:"onyx-sample-result", content: "Nothing picked yet."} + ]} + ], + create: function() { + this.inherited(arguments); + // month + var months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]; + var d = new Date(); + var i, m; + for (i=0; (m=months[i]); i++) { + this.$.monthPicker.createComponent({content: m, active: i==d.getMonth()}); + } + // day + for (i=0; i<30; i++) { + this.$.dayPicker.createComponent({content: i+1, active: i==d.getDate()-1}); + } + // year + var y = d.getYear(); + this.$.yearPicker.setSelected(y); + this.$.yearPickerButton.setContent(1900+y); + }, + setupYear: function(inSender, inEvent) { + this.$.year.setContent(1900+inEvent.index); + }, + itemSelected: function(inSender, inEvent) { + this.$.pickerSelection.setContent(inEvent.selected.content); + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/PopupSample.html b/lib/onyx/samples/PopupSample.html new file mode 100644 index 0000000..0135421 --- /dev/null +++ b/lib/onyx/samples/PopupSample.html @@ -0,0 +1,22 @@ + + + + + Popup Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/PopupSample.js b/lib/onyx/samples/PopupSample.js new file mode 100644 index 0000000..0c5d8e4 --- /dev/null +++ b/lib/onyx/samples/PopupSample.js @@ -0,0 +1,65 @@ +enyo.kind({ + name: "onyx.sample.PopupSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Popups"}, + {classes: "onyx-sample-tools", components: [ + {kind: "onyx.Button", content: "Basic Popup", ontap: "showPopup", popup: "basicPopup"}, + {name: "basicPopup", kind: "onyx.Popup", centered: true, floating: true, classes:"onyx-sample-popup", style: "padding: 10px;", content: "Popup..."}, + {tag: "br"}, + {kind: "onyx.Button", content: "Popup w/Spinner (Dark)", ontap: "showPopup", popup: "spinnerPopup"}, + {name: "spinnerPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", centered: true, floating: true, onHide: "popupHidden", scrim: true, components: [ + {kind: "onyx.Spinner"}, + {content: "Popup"} + ]}, + {tag: "br"}, + {kind: "onyx.Button", content: "Popup w/Spinner (Light)", ontap: "showPopup", popup: "lightPopup"}, + {name: "lightPopup", classes: "onyx-sample-popup", style: "background: #eee;color: black;", kind: "onyx.Popup", centered: true, floating: true, onHide: "popupHidden", scrim: true, components: [ + {kind: "onyx.Spinner", classes: "onyx-light"}, + {content: "Popup"} + ]}, + {tag: "br"}, + {kind: "onyx.Button", content: "Modal Popup with Input", ontap: "showPopup", popup: "modalPopup"}, + {name: "modalPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input"} + ]}, + {tag: "br"}, + {kind: "onyx.Button", content: "Close", ontap: "closeModalPopup"}, + {kind: "onyx.Button", content: "Another!", ontap: "showPopup", popup: "lightPopup"} + ]}, + {tag: "br"}, + {kind: "onyx.Button", content: "Popup at Event (right)", ontap: "showPopupAtEvent", popup: "rightEventPopup", style: "float: right;"}, + {kind: "onyx.Button", content: "Popup at Event", ontap: "showPopupAtEvent", popup: "leftEventPopup"}, + {name: "leftEventPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", modal: true, floating: true, content: "Anchor defaults
    to top left corner", allowHtml: true}, + {name: "rightEventPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", modal: true, floating: true, content: "Adjusts anchor to
    stay in viewport", allowHtml: true} + ]} + ], + showPopup: function(inSender) { + var p = this.$[inSender.popup]; + if (p) { + p.show(); + } + }, + showPopupAtEvent: function(inSender, inEvent) { + var p = this.$[inSender.popup]; + if (p) { + p.showAtEvent(inEvent); + } + }, + popupHidden: function() { + // FIXME: needed to hide ios keyboard + document.activeElement.blur(); + if(this.$.modalPopup.showing) { // Refocus input on modal + enyo.job("focus", enyo.bind(this.$.input, "focus"), 500); + } + }, + popupShown: function() { + // FIXME: does not focus input on android. + this.$.input.focus(); + enyo.job("focus", enyo.bind(this.$.input, "focus"), 500); + }, + closeModalPopup: function() { + this.$.modalPopup.hide(); + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/ProgressSample.html b/lib/onyx/samples/ProgressSample.html new file mode 100644 index 0000000..5c1213f --- /dev/null +++ b/lib/onyx/samples/ProgressSample.html @@ -0,0 +1,22 @@ + + + + + Progress Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ProgressSample.js b/lib/onyx/samples/ProgressSample.js new file mode 100644 index 0000000..b9d65f8 --- /dev/null +++ b/lib/onyx/samples/ProgressSample.js @@ -0,0 +1,81 @@ +enyo.kind({ + name: "onyx.sample.ProgressSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Progress Bars"}, + {kind: "onyx.ProgressBar", progress: 25}, + {kind: "onyx.ProgressBar", animateStripes: false, progress: 25}, + {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-green"}, + {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-red"}, + {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-dark"}, + {kind: "onyx.ProgressBar", animateStripes: false, barClasses: "onyx-light", progress: 50}, + {kind: "onyx.ProgressBar", showStripes: false, progress: 75}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Progress Buttons"}, + {kind: "onyx.ProgressButton", progress: 25, onCancel:"clearValue", components: [ + {content: "0"}, + {content: "100", style: "float: right;"} + ]}, + {kind: "onyx.ProgressButton", animateStripes: false, barClasses: "onyx-dark", progress: 50, onCancel:"clearValue"}, + {kind: "onyx.ProgressButton", showStripes: false, progress: 75, onCancel:"clearValue"}, + {tag: "br"}, + {kind: "onyx.InputDecorator", style:"margin-right:10px;", components: [ + {kind: "onyx.Input", placeholder: "Value", style:"width:50px;"} + ]}, + {kind: "onyx.Button", content:"Set", classes:"onyx-sample-spaced-button", ontap:"changeValue"}, + {kind: "onyx.Button", content:"-", classes:"onyx-sample-spaced-button", ontap:"decValue"}, + {kind: "onyx.Button", content:"+", classes:"onyx-sample-spaced-button", ontap:"incValue"}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Checkbox", name:"animateSetting", checked:true}, + {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"}, + {tag: "br"}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Sliders"}, + {kind: "onyx.Slider", min: 10, max: 50, value: 30}, + {tag: "br"}, + {kind: "onyx.Slider", lockBar: false, progress: 20, value: 75}, + {tag: "br"}, + {name: "progressSlider", kind: "onyx.Slider", lockBar: false, value: 75}, + {kind: "onyx.Button", content: "Toggle Progress", ontap: "toggleProgress"} + ], + changeValue: function(inSender, inEvent) { + for (var i in this.$) { + if (this.$[i].kind == "onyx.ProgressBar" || this.$[i].kind == "onyx.ProgressButton") { + if (this.$.animateSetting.getValue()) { + this.$[i].animateProgressTo(this.$.input.getValue()); + } else { + this.$[i].setProgress(this.$.input.getValue()); + } + } + } + }, + incValue: function() { + this.$.input.setValue(Math.min(parseInt(this.$.input.getValue() || 0, 10) + 10, 100)); + this.changeValue(); + }, + decValue: function() { + this.$.input.setValue(Math.max(parseInt(this.$.input.getValue() || 0, 10) - 10, 0)); + this.changeValue(); + }, + clearValue: function(inSender, inEvent) { + inSender.setProgress(0); + }, + toggleProgress: function() { + this._progressing = !this._progressing; + this.nextProgress(); + }, + nextProgress: function() { + if (this._progressing) { + enyo.requestAnimationFrame(enyo.bind(this, function() { + this.incrementProgress(); + setTimeout(enyo.bind(this, "nextProgress"), 500); + }), this.hasNode()); + } + }, + incrementProgress: function() { + var p = this.$.progressSlider; + var i = p.min + ((p.progress - p.min + 5) % (p.max - p.min + 1)); + p.animateProgressTo(i); + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/SliderSample.html b/lib/onyx/samples/SliderSample.html new file mode 100644 index 0000000..b3c52d0 --- /dev/null +++ b/lib/onyx/samples/SliderSample.html @@ -0,0 +1,22 @@ + + + + + Slider Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/SliderSample.js b/lib/onyx/samples/SliderSample.js new file mode 100644 index 0000000..1f37d4a --- /dev/null +++ b/lib/onyx/samples/SliderSample.js @@ -0,0 +1,98 @@ +enyo.kind({ + name: "onyx.sample.SliderSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Sliders"}, + {kind: "onyx.Slider", value: 50, onChanging:"sliderChanging", onChange:"sliderChanged"}, + {tag: "br"}, + {kind: "onyx.Slider", lockBar: false, value: 50, onChanging:"sliderChanging", onChange:"sliderChanged"}, + + {tag: "br"}, + {kind: "onyx.InputDecorator", style:"margin-right:10px;", components: [ + {kind: "onyx.Input", placeholder: "Value", style:"width:50px;"} + ]}, + {kind: "onyx.Button", content:"Set", classes:"onyx-sample-spaced-button", ontap:"changeValue"}, + {kind: "onyx.Button", content:"-", classes:"onyx-sample-spaced-button", ontap:"decValue"}, + {kind: "onyx.Button", content:"+", classes:"onyx-sample-spaced-button", ontap:"incValue"}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Checkbox", name:"animateSetting", value:true}, + {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"}, + {kind: "onyx.Checkbox", onchange: "sliderIncrementChanged", checked: false}, + {content: "increment by 7", classes:"enyo-inline"}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No slider moved yet."} + ]}, + {tag: "br"}, + {tag: "br"}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "RangeSlider"}, + {tag: "br"}, + {kind: "onyx.RangeSlider", rangeMin: 100, rangeMax: 500, rangeStart: 200, rangeEnd: 400, increment: 20, showLabels: true, onChanging: "rangeSliderChanging", onChange: "rangeSliderChanged"}, + {components: [ + {style: "width:20%; display:inline-block; text-align:left;", content: "$100"}, + {style: "width:60%; display:inline-block; text-align:center;", content: "$300"}, + {style: "width:20%; display:inline-block; text-align:right;", content: "$500"} + ]}, + {tag: "br"}, + {kind: "onyx.Checkbox", onchange: "rangeSliderIncrementChanged", checked: true}, + {content: "increment by 20", classes:"enyo-inline"}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"rangeSliderResult", classes:"onyx-sample-result", content:"RangeSlider not moved yet."} + ]} + ], + changeValue: function(inSender, inEvent) { + for (var i in this.$) { + if (this.$[i].kind == "onyx.Slider") { + if (this.$.animateSetting.getValue()) { + this.$[i].animateTo(this.$.input.getValue()); + } else { + this.$[i].setValue(this.$.input.getValue()); + } + } + } + }, + incValue: function() { + this.$.input.setValue(Math.min(parseInt(this.$.input.getValue() || 0, 10) + 10, 100)); + this.changeValue(); + }, + decValue: function() { + this.$.input.setValue(Math.max(parseInt(this.$.input.getValue() || 0, 10) - 10, 0)); + this.changeValue(); + }, + sliderChanging: function(inSender, inEvent) { + this.$.result.setContent(inSender.name + " changing: " + Math.round(inSender.getValue())); + }, + sliderChanged: function(inSender, inEvent) { + this.$.result.setContent(inSender.name + " changed to " + Math.round(inSender.getValue()) + "."); + }, + rangeSliderIncrementChanged: function(inSender, inEvent) { + this.$.rangeSlider.setIncrement(inSender.getValue() ? 20 : 0); + }, + sliderIncrementChanged: function(inSender, inEvent) { + this.$.slider2.setIncrement(inSender.getValue() ? 7 : 0); + this.$.slider.setIncrement(inSender.getValue() ? 7 : 0); + }, + updateRangeLabels: function(slider) { + slider.setStartLabel("--> " + Math.floor(slider.getRangeStart())); + slider.setEndLabel(Math.floor(slider.getRangeEnd()) + "<--"); + }, + rangeSliderChanging: function(inSender, inEvent) { + this.updateRangeLabels(inSender); + this.$.rangeSliderResult.setContent("Range changing: $" + Math.round(inSender.getRangeStart()) + " - $" + Math.round(inSender.getRangeEnd())); + }, + rangeSliderChanged: function(inSender, inEvent) { + this.updateRangeLabels(inSender); + this.$.rangeSliderResult.setContent("Range changed to $" + Math.round(inSender.getRangeStart()) + " - $" + Math.round(inSender.getRangeEnd()) + "."); + }, + create: function() { + this.inherited(arguments); + this.updateRangeLabels(this.$.rangeSlider); + } +}); diff --git a/lib/onyx/samples/SpinnerSample.html b/lib/onyx/samples/SpinnerSample.html new file mode 100644 index 0000000..c13ed23 --- /dev/null +++ b/lib/onyx/samples/SpinnerSample.html @@ -0,0 +1,22 @@ + + + + + Spinner Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/SpinnerSample.js b/lib/onyx/samples/SpinnerSample.js new file mode 100644 index 0000000..f04cff1 --- /dev/null +++ b/lib/onyx/samples/SpinnerSample.js @@ -0,0 +1,18 @@ +enyo.kind({ + name: "onyx.sample.SpinnerSample", + classes: "onyx onyx-sample", + handlers: { + onSelect: "itemSelected" + }, + components: [ + {classes: "onyx-sample-divider", content: "Light Spinner"}, + {style:"background:black; border-radius:5px; padding:15px", components: [ + {kind: "onyx.Spinner"} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Dark Spinner"}, + {style:"background:white; border-radius:5px; padding:15px", components: [ + {kind: "onyx.Spinner", classes: "onyx-light"} + ]} + ] +}); diff --git a/lib/onyx/samples/TimePickerSample.html b/lib/onyx/samples/TimePickerSample.html new file mode 100644 index 0000000..dc4de12 --- /dev/null +++ b/lib/onyx/samples/TimePickerSample.html @@ -0,0 +1,23 @@ + + + + + TimePicker Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/TimePickerSample.js b/lib/onyx/samples/TimePickerSample.js new file mode 100644 index 0000000..2be02d4 --- /dev/null +++ b/lib/onyx/samples/TimePickerSample.js @@ -0,0 +1,100 @@ +enyo.kind({ + name: "onyx.sample.TimePickerSample", + kind: "FittableRows", + classes: "onyx enyo-fit", + handlers: { + onSelect: "updateTimeValues" + }, + components: [ + {kind: "onyx.Toolbar", content:$L("Times")}, + {kind: "FittableColumns", style: "padding: 10px", components:[ + {components: [ + {content:$L("Choose Locale:"), classes:"onyx-sample-divider"}, + {kind: "onyx.PickerDecorator", style:"padding:10px;", onSelect: "pickerHandler", components: [ + {content: "Pick One...", style: "width: 200px"}, + {kind: "onyx.Picker", components: [ + {content: 'en_us', active:true}, + {content: 'en_ca'}, + {content: 'en_ie'}, + {content: 'en_gb'}, + {content: 'en_mx'}, + {content: 'de_de'}, + {content: 'fr_fr'}, + {content: 'fr_ca'}, + {content: 'it_it'}, + {content: 'es_es'}, + {content: 'es_mx'}, + {content: 'es_us'} + ]} + ]} + ]} + ]}, + + {kind:"onyx.Button",content:"Get Times", style:"margin:10px;", ontap:"getTimes"}, + {kind:"onyx.Button",content:"Reset Times", ontap:"resetTimes"}, + + {style:"width:100%;height:5px;background-color:black;margin-bottom:5px;"}, + {caption: "Dates", style: "padding: 10px", components: [ + {content:"TIME",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"timePicker1", kind:"onyx.TimePicker"} + ]}, + {kind: "onyx.Groupbox", style:"padding:5px;", components: [ + {kind: "onyx.GroupboxHeader", content: "Value"}, + {name:"timePicker1Value", style:"padding:15px;"} + ]}, + {content:"TIME 24 HOUR MODE",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"timePicker2", kind:"onyx.TimePicker", is24HrMode:true} + ]}, + {kind: "onyx.Groupbox", style:"padding:5px;", components: [ + {kind: "onyx.GroupboxHeader", content: "Localized Value"}, + {name:"timePicker2Value", style:"padding:15px;"} + ]}, + {content:"DISABLED",classes:"onyx-sample-divider"}, + {classes: "onyx-toolbar-inline", components: [ + {name:"timePicker3", kind:"onyx.TimePicker", disabled: true} + ]} + ]} + ], + initComponents: function() { + this.inherited(arguments); + this.locale = enyo.g11n.currentLocale().getLocale(); + }, + pickerHandler: function(inSender, inEvent){ + this.locale = inEvent.selected.content; + this.formatTime(); + return true; + }, + formatTime: function(){ + this.$.timePicker1.setLocale(this.locale); + this.$.timePicker2.setLocale(this.locale); + this.$.timePicker2.setIs24HrMode(true); + this.$.timePicker3.setLocale(this.locale); + }, + resetTimes: function(date) { + var d = new Date(); + this.$.timePicker1.setValue(d); + this.$.timePicker2.setValue(d); + this.$.timePicker3.setValue(d); + + this.getTimes(); + }, + getTimes: function(){ + var fmt = new enyo.g11n.DateFmt({ + time: "short", + locale: new enyo.g11n.Locale(this.locale) + }); + + this.$.timePicker1Value.setContent(fmt.format(this.$.timePicker1.getValue())); + this.$.timePicker2Value.setContent(fmt.format(this.$.timePicker2.getValue())); + }, + updateTimeValues: function(inSender, inEvent){ + var fmt = new enyo.g11n.DateFmt({ + time: "short", + locale: new enyo.g11n.Locale(this.locale) + }); + + this.$[inEvent.name + "Value"].setContent(fmt.format(inEvent.value)); + } +}); \ No newline at end of file diff --git a/lib/onyx/samples/ToggleButtonSample.html b/lib/onyx/samples/ToggleButtonSample.html new file mode 100644 index 0000000..17ebff7 --- /dev/null +++ b/lib/onyx/samples/ToggleButtonSample.html @@ -0,0 +1,22 @@ + + + + + ToggleButton Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ToggleButtonSample.js b/lib/onyx/samples/ToggleButtonSample.js new file mode 100644 index 0000000..a0958ea --- /dev/null +++ b/lib/onyx/samples/ToggleButtonSample.js @@ -0,0 +1,35 @@ +enyo.kind({ + name: "onyx.sample.ToggleButtonSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "Toggle Buttons"}, + {classes: "onyx-sample-tools", components: [ + {kind:"onyx.ToggleButton", onChange:"toggleChanged", value: true}, + {kind:"onyx.ToggleButton", onChange:"toggleChanged"}, + {kind:"onyx.ToggleButton", onChange:"toggleChanged"}, + {kind:"onyx.ToggleButton", onChange:"toggleChanged", value: true, disabled: true} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Toggle Buttons Group"}, + {kind: "Group", classes: "onyx-sample-tools group", onActivate:"groupActivated", highlander: true, components: [ + {kind:"onyx.ToggleButton"}, + {kind:"onyx.ToggleButton", value: true}, + {kind:"onyx.ToggleButton"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", content: "Result"}, + {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} + ]} + ], + toggleChanged: function(inSender, inEvent) { + this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); + }, + ordinals: ["1st", "2nd", "3rd"], + groupActivated: function(inSender, inEvent) { + if (inEvent.originator.getActive()) { + var selected = inEvent.originator.indexInContainer(); + this.$.result.setContent("The " + this.ordinals[selected] + " toggle button in the group is selected."); + } + } +}); diff --git a/lib/onyx/samples/ToolbarSample.html b/lib/onyx/samples/ToolbarSample.html new file mode 100644 index 0000000..1c435f4 --- /dev/null +++ b/lib/onyx/samples/ToolbarSample.html @@ -0,0 +1,23 @@ + + + + + Toolbar Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/ToolbarSample.js b/lib/onyx/samples/ToolbarSample.js new file mode 100644 index 0000000..26d5bb5 --- /dev/null +++ b/lib/onyx/samples/ToolbarSample.js @@ -0,0 +1,66 @@ +enyo.kind({ + name: "onyx.sample.ToolbarSample", + classes: "onyx onyx-sample", + components: [ + {classes: "onyx-sample-divider", content: "ToolBar"}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Grabber"}, + {content: "Header"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.Button", content: "Down", classes: "active"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Input"} + ]}, + {kind: "onyx.Button", content: "Right"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Right Input"} + ]}, + {kind: "onyx.Button", content: "More Right"}, + {content: "There's more"}, + {kind: "onyx.Button", content: "Far Right"} + ]}, + {tag: "br"}, + + {classes: "onyx-sample-divider", content: "Scrolling ToolBar"}, + {kind: "Scroller", classes:"onyx-toolbar", touchOverscroll:false, touch:true, vertical:"hidden", style:"margin:0px;", thumb:false, components: [ + {classes: "onyx-toolbar-inline", style: "white-space: nowrap;", components: [ + {kind: "onyx.Grabber"}, + {content: "Header"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.Button", content: "Down", classes: "active"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Input"} + ]}, + {kind: "onyx.Button", content: "Right"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Right Input"} + ]}, + {kind: "onyx.Button", content: "More Right"}, + {content: "There's more"}, + {kind: "onyx.Button", content: "Far Right"} + ]} + ]}, + {tag: "br"}, + + {classes: "onyx-sample-divider", content: "More ToolBar"}, + {kind: "onyx.MoreToolbar", components: [ + {kind: "onyx.Grabber"}, + {content: "Header"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.Button", content: "Down", classes: "active"}, + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Input"} + ]}, + {kind: "onyx.Button", content: "Right"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Right Input"} + ]}, + {kind: "onyx.Button", content: "More Right"}, + {content: "There's more"}, + {kind: "onyx.Button", content: "Far Right"} + ]} + ] +}); diff --git a/lib/onyx/samples/TooltipSample.html b/lib/onyx/samples/TooltipSample.html new file mode 100644 index 0000000..0c2fc32 --- /dev/null +++ b/lib/onyx/samples/TooltipSample.html @@ -0,0 +1,22 @@ + + + + + Tooltip Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/onyx/samples/TooltipSample.js b/lib/onyx/samples/TooltipSample.js new file mode 100644 index 0000000..56c5ddf --- /dev/null +++ b/lib/onyx/samples/TooltipSample.js @@ -0,0 +1,92 @@ +enyo.kind({ + name: "onyx.sample.TooltipSample", + classes: "onyx onyx-sample", + handlers: { + onSelect: "itemSelected" + }, + components: [ + {classes: "onyx-sample-divider", content: "Tooltips on Toolbar"}, + {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.Button", content: "Tooltip"}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} + ]}, + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", style:"width:130px;", placholder: "Just an input..."} + ]}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ + {kind: "onyx.MenuDecorator", components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.Tooltip", content: "Bookmarks menu"}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]}, + {kind: "onyx.MenuDecorator", components: [ + {content: "Bookmarks menu"}, + {kind: "onyx.Tooltip", content: "Tap to open..."}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]} + ]}, + {tag: "br"}, + {classes: "onyx-sample-divider", content: "Tooltips on items"}, + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.Button", content: "Tooltip"}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} + ]}, + {tag: "br"}, + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", style:"width:130px;", placholder: "Just an input..."} + ]}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} + ]}, + {tag: "br"}, + {kind: "onyx.MenuDecorator", components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {kind: "onyx.Tooltip", content: "Bookmarks menu"}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]}, + {tag: "br"}, + {kind: "onyx.MenuDecorator", components: [ + {content: "Bookmarks menu"}, + {kind: "onyx.Tooltip", content: "Tap to open..."}, + {kind: "onyx.Menu", components: [ + {components: [ + {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, + {content: "Bookmarks"} + ]}, + {content: "Favorites"}, + {classes: "onyx-menu-divider"}, + {content: "Recents"} + ]} + ]} + ] +}); \ No newline at end of file diff --git a/lib/onyx/samples/assets/favicon.ico b/lib/onyx/samples/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..52c86347fe3e10042c05374362757fa260307d50 GIT binary patch literal 1150 zcmb`FKMnyw7{#BEC=@o4NK}++2k<9R=-ogfBntOXlHdvyYK=~#aR8MgC>3JNvw6v6 zt=*BB&9}4j&HUcH{bqoSeS!e?UBfsBlmXOj*p$tLdE23F=SqbzI8JMq)4}u`6~jJl zZFFAje9-(^L+ot9~P>KuLiljZ#*QyLTN*h)Z)-7tuxc<+}W4A&)v>)&+2;)f{|&l(I5IHC->x@ z?|k3;KHu{^?|Xp%@n9D+>FKARypb{PX5F;bnTFk2*R(`UR>PHQjg`t(q%#?3u~?QH zqTyV!y=9`KqhoM+TibyL9)9@!|2lwYp85F$t5&aiI@Zw0-uv^17#JKzC>F)gsnbZd zwPC}Tzl5tcT1qmzTTJ@xqG`@d*?;ok*tW_q!I^Olv2hmJrX zjIZ6Y72VxksFW)ZB?+QWf7_O6FT4G*hkn2U0SWcG;XN}<6N)S&lgpu4Ttrn?=|2N? zLx-%_X&W1Yz{57`2!}&>_wWZ!>g?HlrS#m+fq?|MDIt#%EC~Qshl2FfLOFj1*{QcMG}C}| z!9q~f5cGrQDbOtmsuhB2hat-q$Vv@sx|3*XjN(@>9B`OXee{)=Ui;a31Gwk@`}^bZ zmJ>U_eWyYGV$lpEHsLwjoia|;i?DXeIU zLE?FA-Fltx)qMw^psl{K1c3+deXuvSqW#Q6_ub3sM5v%Y0FE)_OGPX!%zIOVks$oR zFhoKo5v;&;8e#HH;9x^HEGVi1$FhirCUjkcNre62!{dlIO6cosC(cChi(fu(W#$Wg zFTC)|xJS581JHcjjw>#|jB^MFcVoseRFx`nF58KG8o?|pDzrMmZDj#H1%LT9__Ke2 zVL6n&1-~SKBU<6q-#hFa(@Iig*-yWggDxyNLe&M=+QOo9xP>U@Y6F4J|L&Kp;R; z)hQW`j;D_Pi~H!T*_I^%L}RhF(MTAUsiUG)P*X}?02;x{;ATjKp$r227)0X?oLUOp z*ffOkJOnk3#+M%fCud;`68VDtNf2}dw*3jB<%&W98Hf`i!EkWxk^o|nXp3tg?mup( zHW`Ylso-c+juXK1eh5+sOlktp)gYXlgYR!-I*JY`Wk|{h63=`cv9oVOBm=VPJ(Gek z3@xTAhxE zc~SE8EAk@5fJ_lrp?5aG>IuTPk`Rdt(8d=???gzEE+3&l5TiDZpIBoMhK^#zq36Jn zWAel&cO91-?&b=an{L|j5(H#fP7!n0T3*SpDN0&fAQZ^m5Nx8ENeH|OAGvuYlEBnV z0X9`WsWF5^go7;DNLN&RKUjj|WH7h9hlofVs_R~zh%mobC(4yNs#PM;=L4Y0$MU({ z+V*8F?qPUAh!R67uadT_aJXqm#tGQ+Jjp2xwQfSabQi>-w@?@wMsJLvDbH{w)Pls5 zBT&m_IEAc7UKen;mbmCnkeOM!b!@2&dEwyX#FS?^0#BqPLJCv|VzCJEq8FxcDJ-E8 zc3T|2WmRxJy-41;4b4xziSA?+_No?qe9?O3mv1Jg6u~I#Pn^!>7Ec}_lB#SBkBq}| zoP$dc$feV7o*5CRue|Dt4xh-oVR)}MHz&vmvoQFL(77S#4KY%}B0`~C;lz3o`rY^7 zY$y4u{fMmEj@F)Qpw%iQMV%TG@)9y6pG4)Ev^Aeu#MIREsGW&!76e%+7{u)S0s?*_rcb46*NzOk14ekQ*PL+ODnu$u>4v+&T5q6~d{AYD zTvJA^M!#~+vuc6(bo}_oPBv3`_~@gZy(_ynx3)Dw;zURx2`!0) z*ZIs>x*+-d2nGe>QW$?wNPrHzhmf>>Esl77E)#@aj52>iwRAg*&N9MU4xg8ZA zO{YdhY4#Xz>eMY!y(myqvbb3Eyx(nNWX-}~j~&nOO6}&;BO{CF4Zs~oj~*>wd;OL} zsnOJ}O^KFZK9?mq3SJ*rC>A_Y*=}n>S-Q^VdcHxINg6kZWNy1wt5vaBD3EjdQK338 zbaJp%SM<9yAD?Pkz1sQijvcm}>^TE)$KgYV(wjDJ{Nw4fGxsDrI=KQlUdZo5iKHdd z`8u?@ZQ0(Y79rtUuIu@_u6wX+nvPI3PIDZjMh5kQ&YpBQX~r^nM=+R~8mX9*lY`cI z1MrUH@ZntlfrDGtU$L>XtFs4w>JJ#n(;%2#iFyJjG^n=1=L=E;8bu%&p%s0Ynaf~i zB1Mg0&)c?< zR}H<)I8lxI{U-M8vA+-jcT7)Cl;&oqlf_~_K_m+~WTmb&9fH49E+L&xV`g>+)3Z}Z zQx}{gr4*@w$Yp`o~oPXG%p$XT+}DO^Wux2wdWV|ZP-p$w!N>f z@20i={avwGED?&vqTxs=Xqk>6D+-ab zlxkyRec-w0sMh}L2g(I~oc?3DMfYO5y2-)YNZc{O-;_-=< qt*zB<+qPMI_Uv(Rp0A?+i}81Zn+pU9Zr=O=0000o!!~4C?;@{e`j{)%=!QG{r96-mc^drP}vh6 z&jirKjiM<3DPv)K{~rYM3?JqNiTo}?XNfXIDO|HFh9ZwEa=n!7-@m_w=1k`!npXoM zSH!mv1WHCnNBQED9`n`!h1BCvfr57&@~TKAQcc&i$68#-grp{}3KQR@ac>pkhMakD z_wL=blarHOsZ{FQwzjsHpx>O-($dmIkX|6VLNvs$x~~6l`}XZm>0OBC1hBRz0{mHJ zZ*TACwY9a|=zeZ-ak0`10mCr(oZsYU!C=rw%-a76$|Jd0tgglC1b0>cNT;y$PLBEx)kY_ z{*za*BS(&C1S>m!{J22~xyBg~|5ld*owAZpoRSiifRY_Nc+lwS>3M*~>bknRREcTc zbqY?$rfCYuby9~##EnoVgPbSkSLyy|PA5*B7&&+D+&tzQIe2gc(#0gB6n1ZtMImOP-KTwqO1OeAU8 zN#yY1!>x2Jm1+VWP^v+dc*ftAA==d-GgfzZckkqD%+Aj0xss70Tm&T<|5-)!^2w7Y zcXV`gaLKsBzz}xP9CM8jHeR1z$HKG%%6Rc*qM9 z#BrZnB+FHCLFWlT9>rRwmkr1v(}yA=fP1wF1Pr+5vWh653ZAaM;E4;MJoW9l_WpOz z+H=pwRFxW3P0Dgi>V8c4ytvOk4gq`!%Rywi3S5Iyd7Y6`bPQL0C0(-Sp`IW@F;Bg< zQVJHiA%U@pCYY83 zc0ZUm5N!wr+0Nd#*vI*HLf&)=2!(+}45~;V5hdLYF*L`{{m^qccK#wSNHSU0RsfpY zku@tN6hyN!2Z~9ylXVk7lw2Xey^&}O&D>Ie0GqLBDQbuq)G&uyK-7h%T*7M(_{;Ed zeTAR3ezb+{X$`Ta&n|n%i!zOcPQSx;$U4*S`9deQjiIn=zzj)^rM>0eV}2 zjyASuTeWR`MUUtFtn|$n*bYiJ*;Bu;KA;klRN*SXDotf;Y3I%S;TKoPqLSXs5{7Mv zBY>OhSbL+6HGR^?THC7GD^P2tRADa*#XcBOd8MCK`_)J9u0{&pa12Ff7}wd0leREi zJtYWa<=~;_vH?5tS&t^IbWEdVyNCZ(j$&4ncYZek6sZpMS;ZwO!F(KRt;UX>b*3*D z0*XYr52MJ@&WzHBw8RG+XeH%u0!*WC6p1VDI4|%F#cs@Xz-Ie#-wl@h{+|7x7gI+2 z#wD0V-JixfPNtR{4=qPy`jFU4Lnc-6!T3MK&C~!&2L8*z4pm>yQuTAaKA1 zO~s9e>T;}NIX+C%pZRc{Eq*z|zQGCD25k z$%w0<{M{zjXzS3h*Nr1B>vE5%Ihs;FAxg|=ew0Cevk&tRaLq^aU2~EciVvYn-Xp+iGO^dT(vAoK1xpYpme|bDRp!idO0RR(9 V6nWnJ%Dn&p002ovPDHLkV1n6ngEIgC literal 0 HcmV?d00001 diff --git a/lib/onyx/samples/assets/search-input-search.png b/lib/onyx/samples/assets/search-input-search.png new file mode 100644 index 0000000000000000000000000000000000000000..36bf1b5161e9d6b22273b681e43c85859c7c8914 GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O literal 0 HcmV?d00001 diff --git a/lib/onyx/samples/package.js b/lib/onyx/samples/package.js new file mode 100644 index 0000000..1ce23d6 --- /dev/null +++ b/lib/onyx/samples/package.js @@ -0,0 +1,23 @@ +enyo.depends( + "sample.css", + "DrawerSample.css", + "ButtonGroupSample.js", + "ButtonSample.js", + "CheckboxSample.js", + "GroupboxSample.js", + "IconButtonSample.js", + "InputSample.js", + "PopupSample.js", + "ProgressSample.js", + "SliderSample.js", + "ToggleButtonSample.js", + "ToolbarSample.js", + "DrawerSample.js", + "MenuSample.js", + "TooltipSample.js", + "SpinnerSample.js", + "PickerSample.js", + "DatePickerSample.js", + "TimePickerSample.js", + "ContextualPopupSample.js" +); \ No newline at end of file diff --git a/lib/onyx/samples/sample.css b/lib/onyx/samples/sample.css new file mode 100644 index 0000000..a06cde6 --- /dev/null +++ b/lib/onyx/samples/sample.css @@ -0,0 +1,43 @@ +.onyx-sample { + padding: 10px; +} +.onyx-sample-tools { + padding-bottom:10px; +} +.onyx-sample-tools > * { + margin: 3px; +} +.onyx-sample-divider { + color: #F49200; + text-transform: uppercase; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; + font-weight: bold; + margin-bottom: 8px; +} +.onyx-sample-result-box { + width:100%; +} +.onyx-sample-result { + padding:8px; +} +.onyx-sample-spaced-button { + margin:3px; +} +.onyx-sample-animate-label { + vertical-align:middle; + padding-left:5px; + margin-right: 15px; +} +.onyx-sample-label { + color: #1879CD; + font-size: 18px; + text-transform: uppercase; +} +.onyx-sample-popup { + font-size: 30px; + text-align: center; +} +.onyx-contextualpopup-button-container{ + padding:10px; +} diff --git a/lib/onyx/source/Button.js b/lib/onyx/source/Button.js new file mode 100644 index 0000000..8385bc2 --- /dev/null +++ b/lib/onyx/source/Button.js @@ -0,0 +1,38 @@ +/** + _onyx.Button_ is an enyo.Button with Onyx styling + applied. The color of the button may be customized by specifying a + background color. + + The *onyx-affirmative*, *onyx-negative*, and *onyx-blue* classes provide + some built-in presets. + + {kind: "onyx.Button", content: "Button"}, + {kind: "onyx.Button", content: "Affirmative", classes: "onyx-affirmative"}, + {kind: "onyx.Button", content: "Negative", classes: "onyx-negative"}, + {kind: "onyx.Button", content: "Blue", classes: "onyx-blue"}, + {kind: "onyx.Button", content: "Custom", style: "background-color: purple; color: #F1F1F1;"} + + For more information, see the documentation on + Buttons in the + Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.Button", + kind: "enyo.Button", + classes: "onyx-button enyo-unselectable", + //* @protected + create: function() { + //workaround for FirefoxOS which doesn't support :active:hover css selectors + if(enyo.platform.firefoxOS) { + this.handlers.ondown = "down"; + this.handlers.onleave = "leave"; + } + this.inherited(arguments); + }, + down: function(inSender, inEvent) { + this.addClass("pressed"); + }, + leave: function(inSender, inEvent) { + this.removeClass("pressed"); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/Checkbox.js b/lib/onyx/source/Checkbox.js new file mode 100644 index 0000000..54155f9 --- /dev/null +++ b/lib/onyx/source/Checkbox.js @@ -0,0 +1,34 @@ +/** + A box that shows or hides a check mark when clicked. + The onChange event is fired when it is clicked. Use getValue() to fetch + the checked status. + + {kind: "onyx.Checkbox", onchange: "checkboxClicked"} + + checkboxClicked: function(inSender) { + if (inSender.getValue()) { + this.log("I've been checked!"); + } + } +*/ +enyo.kind({ + name: "onyx.Checkbox", + classes: "onyx-checkbox", + //* @protected + kind: enyo.Checkbox, + tag: "div", + handlers: { + // prevent double onchange bubble in IE + onclick: "" + }, + tap: function(inSender, e) { + if (!this.disabled) { + this.setChecked(!this.getChecked()); + this.bubble("onchange"); + } + return !this.disabled; + }, + dragstart: function() { + // Override enyo.Input dragstart handler, to allow drags to propagate for Checkbox + } +}); diff --git a/lib/onyx/source/ContextualPopup.js b/lib/onyx/source/ContextualPopup.js new file mode 100644 index 0000000..a236860 --- /dev/null +++ b/lib/onyx/source/ContextualPopup.js @@ -0,0 +1,514 @@ +/** + _onyx.ContextualPopup_ is a subkind of enyo.Popup. + Contextual popups serve as child windows that appear near the point of + initiation. Use them for prompting users to select from a defined set of + options; for conducting other quick, single-step interactions in which + context should be maintained; and for presenting simple views, such as + previews. + + A contextual popup is meant to be used in conjunction with a decorator, such + as an onyx.MenuDecorator. The decorator + couples the popup with an activating control, which may be a button or any + other control with an _onActivate_ event. When the control is activated, the + popup shows itself in the correct position relative to the activator. + + Note that, by default, the popup is not floating, so toolbars and controls + with high z-index values may obscure it. You may set the _floating_ property + to true to have the popup always appear on top; however, the popup will not + be in the containing document's flow and so will not scroll with the + document. + + In addition, while contextual popups have their own positioning logic, they + do not currently have their own sizing logic, so be sure to take this into + account when using them. + + {kind: "onyx.MenuDecorator", components: [ + {content: "Show Popup"}, + {kind: "onyx.ContextualPopup", + title: "Sample Popup", + actionButtons: [ + {content:"Button 1", classes: "onyx-button-warning"}, + {content:"Button 2"} + ], + components: [ + {content:"Sample component in popup"} + ] + } + ]} +*/ + +enyo.kind({ + name: "onyx.ContextualPopup", + kind: "enyo.Popup", + modal: true, + autoDismiss: true, + floating:false, + classes: "onyx-contextual-popup enyo-unselectable", + published: { + //* Maximum height of the menu + maxHeight: 100, + //* Toggle scrolling + scrolling: true, + //* Popup title content + title: undefined, + //* Buttons at bottom of popup + actionButtons: [] + }, + + //layout parameters + vertFlushMargin:60, //vertical flush layout margin + horizFlushMargin:50, //horizontal flush layout margin + widePopup:200, //popups wider than this value are considered wide (for layout purposes) + longPopup:200, //popups longer than this value are considered long (for layout purposes) + horizBuffer:16, //do not allow horizontal flush popups past spec'd amount of buffer space on left/right screen edge + + events: { + onTap: "" + }, + handlers: { + onActivate: "itemActivated", + onRequestShowMenu: "requestShow", + onRequestHideMenu: "requestHide" + }, + components: [ + {name:"title", classes:"onyx-contextual-popup-title"}, + {classes:"onyx-contextual-popup-scroller", components:[ + {name:"client", kind: "enyo.Scroller", vertical:"auto", classes:"enyo-unselectable", thumb:false, strategyKind: "TouchScrollStrategy"} + ]}, + {name:"actionButtons", classes:"onyx-contextual-popup-action-buttons"} + ], + scrollerName: "client", + create: function() { + this.inherited(arguments); + this.maxHeightChanged(); + this.titleChanged(); + this.actionButtonsChanged(); + }, + getScroller: function() { + return this.$[this.scrollerName]; + }, + titleChanged: function(){ + this.$.title.setContent(this.title); + }, + actionButtonsChanged: function(){ + for (var i=0;i bottomFlushPt) { + //check/try vertical flush positioning (rule 1.a.i) + if (this.applyVerticalFlushPositioning(leftFlushPt, rightFlushPt)) { + return; + } + + //if vertical doesn't fit then check/try horizontal flush (rule 1.a.ii) + if (this.applyHorizontalFlushPositioning(leftFlushPt, rightFlushPt)) { + return; + } + + //if flush positioning didn't work then try just positioning vertically (rule 1.b.i & rule 1.b.ii) + if (this.applyVerticalPositioning()){ + return; + } + //otherwise check if the activator is in the left or right edges of the view & if so try horizontal positioning + } else if ((this.activatorOffset.left + this.activatorOffset.width) < leftFlushPt || this.activatorOffset.left > rightFlushPt) { + //if flush positioning didn't work then try just positioning horizontally (rule 1.b.iii & rule 1.b.iv) + if (this.applyHorizontalPositioning()){ + return; + } + } + + //Rule 2 - no specific logic below for this rule since it is inheritent to the positioning functions, ie we attempt to never + //position a popup where there isn't enough room for it. + + //Rule 3 - Popup Size based positioning + var clientRect = this.getBoundingRect(this.node); + + //if the popup is wide then use vertical positioning + if (clientRect.width > this.widePopup) { + if (this.applyVerticalPositioning()){ + return; + } + } + //if the popup is long then use horizontal positioning + else if (clientRect.height > this.longPopup) { + if (this.applyHorizontalPositioning()){ + return; + } + } + + //Rule 4 - Favor top or bottom positioning + if (this.applyVerticalPositioning()) { + return; + } + //but if thats not possible try horizontal + else if (this.applyHorizontalPositioning()){ + return; + } + + //Rule 5 - no specific logic below for this rule since it is built into the vertical position functions, ie we attempt to + // use a bottom position for the popup as much possible. + } + }, + //move the popup below or above the activator & verify that it fits on screen + initVerticalPositioning: function() { + this.resetPositioning(); + this.addClass("vertical"); + + var clientRect = this.getBoundingRect(this.node); + var innerHeight = this.getViewHeight(); + + if (this.floating){ + if (this.activatorOffset.top < (innerHeight / 2)) { + this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height, bottom: "auto"}); + this.addClass("below"); + } else { + this.applyPosition({top: this.activatorOffset.top - clientRect.height, bottom: "auto"}); + this.addClass("above"); + } + } else { + //if the popup's bottom goes off the screen then put it on the top of the invoking control + if ((clientRect.top + clientRect.height > innerHeight) && ((innerHeight - clientRect.bottom) < (clientRect.top - clientRect.height))){ + this.addClass("above"); + } else { + this.addClass("below"); + } + } + + //if moving the popup above or below the activator puts it past the edge of the screen then vertical doesn't work + clientRect = this.getBoundingRect(this.node); + if ((clientRect.top + clientRect.height) > innerHeight || clientRect.top < 0){ + return false; + } + + return true; + }, + applyVerticalPositioning: function() { + //if we can't fit the popup above or below the activator then forget vertical positioning + if (!this.initVerticalPositioning()) { + return false; + } + + var clientRect = this.getBoundingRect(this.node); + var innerWidth = this.getViewWidth(); + + if (this.floating){ + //Get the left edge delta to horizontally center the popup + var centeredLeft = this.activatorOffset.left + this.activatorOffset.width/2 - clientRect.width/2; + if (centeredLeft + clientRect.width > innerWidth) {//popup goes off right edge of the screen if centered + this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width - clientRect.width}); + this.addClass("left"); + } else if (centeredLeft < 0) {//popup goes off left edge of the screen if centered + this.applyPosition({left:this.activatorOffset.left}); + this.addClass("right"); + } else {//center the popup + this.applyPosition({left: centeredLeft}); + } + + } else { + //Get the left edge delta to horizontally center the popup + var centeredLeftDelta = this.activatorOffset.left + this.activatorOffset.width/2 - clientRect.left - clientRect.width/2; + if (clientRect.right + centeredLeftDelta > innerWidth) {//popup goes off right edge of the screen if centered + this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width - clientRect.right}); + this.addRemoveClass("left", true); + } else if (clientRect.left + centeredLeftDelta < 0) {//popup goes off left edge of the screen if centered + this.addRemoveClass("right", true); + } else {//center the popup + this.applyPosition({left: centeredLeftDelta}); + } + } + + return true; + }, + applyVerticalFlushPositioning: function(leftFlushPt, rightFlushPt) { + //if we can't fit the popup above or below the activator then forget vertical positioning + if (!this.initVerticalPositioning()) { + return false; + } + + var clientRect = this.getBoundingRect(this.node); + var innerWidth = this.getViewWidth(); + + //If the activator's right side is within our left side cut off use flush positioning + if ((this.activatorOffset.left + this.activatorOffset.width/2) < leftFlushPt){ + //if the activator's left edge is too close or past the screen left edge + if (this.activatorOffset.left + this.activatorOffset.width/2 < this.horizBuffer){ + this.applyPosition({left:this.horizBuffer + (this.floating ? 0 : -clientRect.left)}); + } else { + this.applyPosition({left:this.activatorOffset.width/2 + (this.floating ? this.activatorOffset.left : 0)}); + } + + this.addClass("right"); + this.addClass("corner"); + return true; + } + //If the activator's left side is within our right side cut off use flush positioning + else if (this.activatorOffset.left + this.activatorOffset.width/2 > rightFlushPt) { + if ((this.activatorOffset.left+this.activatorOffset.width/2) > (innerWidth-this.horizBuffer)){ + this.applyPosition({left:innerWidth - this.horizBuffer - clientRect.right}); + } else { + this.applyPosition({left: (this.activatorOffset.left + this.activatorOffset.width/2) - clientRect.right}); + } + this.addClass("left"); + this.addClass("corner"); + return true; + } + + return false; + }, + //move the popup left or right of the activator & verify that it fits on screen + initHorizontalPositioning: function() { + this.resetPositioning(); + + var clientRect = this.getBoundingRect(this.node); + var innerWidth = this.getViewWidth(); + + //adjust horizontal positioning of the popup & nub vertical positioning + if (this.floating){ + if ((this.activatorOffset.left + this.activatorOffset.width) < innerWidth/2) { + this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width}); + this.addRemoveClass("left", true); + } else { + this.applyPosition({left: this.activatorOffset.left - clientRect.width}); + this.addRemoveClass("right", true); + } + } else { + if (this.activatorOffset.left - clientRect.width > 0) { + this.applyPosition({left: this.activatorOffset.left - clientRect.left - clientRect.width}); + this.addRemoveClass("right", true); + } else { + this.applyPosition({left: this.activatorOffset.width}); + this.addRemoveClass("left", true); + } + } + this.addRemoveClass("horizontal", true); + + //if moving the popup left or right of the activator puts it past the edge of the screen then horizontal won't work + clientRect = this.getBoundingRect(this.node); + if (clientRect.left < 0 || (clientRect.left + clientRect.width) > innerWidth){ + return false; + } + return true; + + }, + applyHorizontalPositioning: function() { + //if we can't fit the popup left or right of the activator then forget horizontal positioning + if (!this.initHorizontalPositioning()) { + return false; + } + + var clientRect = this.getBoundingRect(this.node); + var innerHeight = this.getViewHeight(); + var activatorCenter = this.activatorOffset.top + this.activatorOffset.height/2; + + if (this.floating){ + //if the activator's center is within 10% of the center of the view, vertically center the popup + if ((activatorCenter >= (innerHeight/2 - 0.05 * innerHeight)) && (activatorCenter <= (innerHeight/2 + 0.05 * innerHeight))) { + this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height/2 - clientRect.height/2, bottom: "auto"}); + } else if (this.activatorOffset.top + this.activatorOffset.height < innerHeight/2) { //the activator is in the top 1/2 of the screen + this.applyPosition({top: this.activatorOffset.top - this.activatorOffset.height, bottom: "auto"}); + this.addRemoveClass("high", true); + } else { //otherwise the popup will be positioned in the bottom 1/2 of the screen + this.applyPosition({top: this.activatorOffset.top - clientRect.height + this.activatorOffset.height*2, bottom: "auto"}); + this.addRemoveClass("low", true); + } + } else { + //if the activator's center is within 10% of the center of the view, vertically center the popup + if ((activatorCenter >= (innerHeight/2 - 0.05 * innerHeight)) && (activatorCenter <= (innerHeight/2 + 0.05 * innerHeight))) { + this.applyPosition({top: (this.activatorOffset.height - clientRect.height)/2}); + } else if (this.activatorOffset.top + this.activatorOffset.height < innerHeight/2) { //the activator is in the top 1/2 of the screen + this.applyPosition({top: -this.activatorOffset.height}); + this.addRemoveClass("high", true); + } else { //otherwise the popup will be positioned in the bottom 1/2 of the screen + this.applyPosition({top: clientRect.top - clientRect.height - this.activatorOffset.top + this.activatorOffset.height}); + this.addRemoveClass("low", true); + } + } + return true; + }, + applyHorizontalFlushPositioning: function(leftFlushPt, rightFlushPt) { + //if we can't fit the popup left or right of the activator then forget vertical positioning + if (!this.initHorizontalPositioning()) { + return false; + } + + var clientRect = this.getBoundingRect(this.node); + var innerWidth = this.getViewWidth(); + + //adjust vertical positioning (high or low nub & popup position) + if (this.floating){ + if (this.activatorOffset.top < (innerHeight/2)){ + this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height/2}); + this.addRemoveClass("high", true); + } else { + this.applyPosition({top:this.activatorOffset.top + this.activatorOffset.height/2 - clientRect.height}); + this.addRemoveClass("low", true); + } + } else { + if (((clientRect.top + clientRect.height) > innerHeight) && ((innerHeight - clientRect.bottom) < (clientRect.top - clientRect.height))) { + this.applyPosition({top: clientRect.top - clientRect.height - this.activatorOffset.top - this.activatorOffset.height/2}); + this.addRemoveClass("low", true); + } else { + this.applyPosition({top: this.activatorOffset.height/2}); + this.addRemoveClass("high", true); + } + } + + //If the activator's right side is within our left side cut off use flush positioning + if ((this.activatorOffset.left + this.activatorOffset.width) < leftFlushPt){ + this.addClass("left"); + this.addClass("corner"); + return true; + } + //If the activator's left side is within our right side cut off use flush positioning + else if (this.activatorOffset.left > rightFlushPt) { + this.addClass("right"); + this.addClass("corner"); + return true; + } + + return false; + }, + getBoundingRect: function(inNode){ + // getBoundingClientRect returns top/left values which are relative to the viewport and not absolute + var o = inNode.getBoundingClientRect(); + if (!o.width || !o.height) { + return { + left: o.left, + right: o.right, + top: o.top, + bottom: o.bottom, + width: o.right - o.left, + height: o.bottom - o.top + }; + } + return o; + }, + getViewHeight: function() { + return (window.innerHeight === undefined) ? document.documentElement.clientHeight : window.innerHeight; + }, + getViewWidth: function() { + return (window.innerWidth === undefined) ? document.documentElement.clientWidth : window.innerWidth; + }, + resetPositioning: function() { + this.removeClass("right"); + this.removeClass("left"); + this.removeClass("high"); + this.removeClass("low"); + this.removeClass("corner"); + this.removeClass("below"); + this.removeClass("above"); + this.removeClass("vertical"); + this.removeClass("horizontal"); + + this.applyPosition({left: "auto"}); + this.applyPosition({top: "auto"}); + }, + resizeHandler: function() { + this.inherited(arguments); + this.adjustPosition(); + }, + requestHide: function(){ + this.setShowing(false); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/DatePicker.js b/lib/onyx/source/DatePicker.js new file mode 100644 index 0000000..51f32b2 --- /dev/null +++ b/lib/onyx/source/DatePicker.js @@ -0,0 +1,205 @@ +/** + _onyx.DatePicker_ is a group of onyx.Picker + controls displaying the current date. The user may change the _day_, + _month_, and _year_ values. + + By default, _DatePicker_ tries to determine the current locale and use its + rules to format the date (including the month name). In order to do this + successfully, the _g11n_ library must be loaded; if it is not loaded, the + control defaults to using standard U.S. date format. + + The _day_ field is automatically populated with the proper number of days + for the selected month and year. + */ +enyo.kind({ + name: "onyx.DatePicker", + classes: "onyx-toolbar-inline", + published: { + //* If true, control is shown as disabled, and user can't select new values + disabled: false, + /** + Current locale used for formatting. Can be set after control + creation, in which case the control will be updated to reflect the + new value. + */ + locale: "en_us", + //* If true, the day field is hidden + dayHidden: false, + //* If true, the month field is hidden + monthHidden: false, + //* If true, the year field is hidden + yearHidden: false, + //* Optional minimum year value + minYear: 1900, + //* Optional maximum year value + maxYear: 2099, + /** + The current Date object. When a Date object is passed to _setValue_, + the control is updated to reflect the new value. _getValue_ returns + a Date object. + */ + value: null + }, + events: { + /** + Fires when one of the DatePicker's fields is selected. + + _inEvent.name_ contains the name of the DatePicker that generated + the event. + + _inEvent.value_ contains the current Date value of the control. + */ + onSelect: "" + }, + create: function() { + this.inherited(arguments); + if (enyo.g11n) { + this.locale = enyo.g11n.currentLocale().getLocale(); + } + this.initDefaults(); + }, + initDefaults: function() { + // Fall back to en_us as default + var months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]; + + //Attempt to use the g11n lib (ie assume it is loaded) + if (enyo.g11n) { + this._tf = new enyo.g11n.Fmts({locale:this.locale}); + months = this._tf.getMonthFields(); + } + + this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : 'mdy'); + + this.dayHiddenChanged(); + this.monthHiddenChanged(); + this.yearHiddenChanged(); + + //Fill month, year & day pickers with values + var d = this.value = this.value || new Date(); + for (var i=0,m; (m=months[i]); i++) { + this.$.monthPicker.createComponent({content: m, value:i, active: i==d.getMonth()}); + } + + var y = d.getFullYear(); + this.$.yearPicker.setSelected(y-this.minYear); + + for (i=1; i<=this.monthLength(d.getYear(), d.getMonth()); i++) { + this.$.dayPicker.createComponent({content:i, value:i, active: i==d.getDate()}); + } + }, + monthLength: function(inYear, inMonth) { + // determine number of days in a particular month/year + return 32 - new Date(inYear, inMonth, 32).getDate(); + }, + setupYear: function(inSender, inEvent) { + this.$.year.setContent(this.minYear+inEvent.index); + }, + setupPickers: function(ordering) { + var orderingArr = ordering.split(""); + var o,f,l; + for(f = 0, l = orderingArr.length; f < l; f++) { + o = orderingArr[f]; + switch (o){ + case 'd': this.createDay(); + break; + case 'm': this.createMonth(); + break; + case 'y': this.createYear(); + break; + default: break; + } + } + }, + createYear: function() { + var yearCount = this.maxYear - this.minYear; + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateYear", components: [ + {classes:"onyx-datepicker-year", name: "yearPickerButton", disabled: this.disabled}, + {name: "yearPicker", kind: "onyx.FlyweightPicker", count: ++yearCount, onSetupItem: "setupYear", components: [ + {name: "year"} + ]} + ]} + ); + }, + createMonth: function() { + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateMonth", components: [ + {classes:"onyx-datepicker-month", name: "monthPickerButton", disabled: this.disabled}, + {name: "monthPicker", kind: "onyx.Picker"} + ]} + ); + }, + createDay: function() { + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateDay", components: [ + {classes:"onyx-datepicker-day", name: "dayPickerButton", disabled: this.disabled}, + {name: "dayPicker", kind: "onyx.Picker"} + ]} + ); + }, + localeChanged: function() { + this.refresh(); + }, + dayHiddenChanged: function() { + this.$.dayPicker.getParent().setShowing(this.dayHidden ? false : true); + }, + monthHiddenChanged: function() { + this.$.monthPicker.getParent().setShowing(this.monthHidden ? false : true); + }, + yearHiddenChanged: function() { + this.$.yearPicker.getParent().setShowing(this.yearHidden ? false : true); + }, + minYearChanged: function() { + this.refresh(); + }, + maxYearChanged: function() { + this.refresh(); + }, + valueChanged: function(){ + this.refresh(); + }, + disabledChanged: function() { + this.$.yearPickerButton.setDisabled(this.disabled); + this.$.monthPickerButton.setDisabled(this.disabled); + this.$.dayPickerButton.setDisabled(this.disabled); + }, + updateDay: function(inSender, inEvent){ + var date = this.calcDate(this.value.getFullYear(), + this.value.getMonth(), + inEvent.selected.value); + this.doSelect({name:this.name, value:date}); + this.setValue(date); + return true; + }, + updateMonth: function(inSender, inEvent){ + var date = this.calcDate(this.value.getFullYear(), + inEvent.selected.value, + this.value.getDate()); + this.doSelect({name:this.name, value:date}); + this.setValue(date); + return true; + }, + updateYear: function(inSender, inEvent){ + //if the node wasn't found (issue around FlyWeightRepeater/Picker) don't update the picker + if (inEvent.originator.selected != -1) { + var date = this.calcDate(this.minYear + inEvent.originator.selected, + this.value.getMonth(), + this.value.getDate()); + this.doSelect({name:this.name, value:date}); + this.setValue(date); + } + return true; + }, + calcDate: function(year, month, day){ + return new Date(year,month,day, + this.value.getHours(), + this.value.getMinutes(), + this.value.getSeconds(), + this.value.getMilliseconds()); + }, + refresh: function(){ + this.destroyClientControls(); + this.initDefaults(); + this.render(); + } +}); diff --git a/lib/onyx/source/Drawer.js b/lib/onyx/source/Drawer.js new file mode 100644 index 0000000..da94338 --- /dev/null +++ b/lib/onyx/source/Drawer.js @@ -0,0 +1,115 @@ +/** + _onyx.Drawer_ is a control that appears or disappears based on its _open_ + property. By default, the drawer appears or disappears with a sliding + animation whose direction is determined by the _orient_ property. + + For more information, see the documentation on + Drawers in the + Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.Drawer", + published: { + //* The visibility state of the drawer's associated control + open: true, + /** + Direction of the opening/closing animation--either "v" for vertical + or "h" for horizontal + */ + orient: "v", + //* If true, the opening/closing transition will be animated. + animated: true + }, + //* @protected + style: "overflow: hidden; position: relative;", + tools: [ + {kind: "Animator", onStep: "animatorStep", onEnd: "animatorEnd"}, + {name: "client", style: "position: relative;", classes: "enyo-border-box"} + ], + create: function() { + this.inherited(arguments); + this.animatedChanged(); + this.openChanged(); + }, + initComponents: function() { + this.createChrome(this.tools); + this.inherited(arguments); + }, + animatedChanged: function() { + if (!this.animated && this.hasNode() && this.$.animator.isAnimating()) { + this.$.animator.stop(); + this.animatorEnd(); + } + }, + openChanged: function() { + this.$.client.show(); + if (this.hasNode()) { + if (this.$.animator.isAnimating()) { + this.$.animator.reverse(); + } else { + var v = this.orient == "v"; + var d = v ? "height" : "width"; + var p = v ? "top" : "left"; + // unfixing the height/width is needed to properly + // measure the scrollHeight/Width DOM property, but + // can cause a momentary flash of content on some browsers + this.applyStyle(d, null); + var s = this.hasNode()[v ? "scrollHeight" : "scrollWidth"]; + if (this.animated) { + this.$.animator.play({ + startValue: this.open ? 0 : s, + endValue: this.open ? s : 0, + dimension: d, + position: p + }); + } else { + // directly run last frame if not animating + this.animatorEnd(); + } + } + } else { + this.$.client.setShowing(this.open); + } + }, + animatorStep: function(inSender) { + // the actual drawer DOM node adjusts its height + if (this.hasNode()) { + var d = inSender.dimension; + this.node.style[d] = this.domStyles[d] = inSender.value + "px"; + } + // while the client inside the drawer adjusts its position to move out of the visible area + var cn = this.$.client.hasNode(); + if (cn) { + var p = inSender.position; + var o = (this.open ? inSender.endValue : inSender.startValue); + cn.style[p] = this.$.client.domStyles[p] = (inSender.value - o) + "px"; + } + if (this.container) { + this.container.resized(); + } + }, + animatorEnd: function() { + if (!this.open) { + this.$.client.hide(); + } + else { + // save changes to this.domCssText --> see ENYO-1561 + this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); + // at end of open animation, clean limit on height/width + var v = (this.orient == "v"); + var d = v ? "height" : "width"; + var p = v ? "top" : "left"; + var cn = this.$.client.hasNode(); + // clear out changes to container position & node dimension + if (cn) { + cn.style[p] = this.$.client.domStyles[p] = null; + } + if (this.node) { + this.node.style[d] = this.domStyles[d] = null; + } + } + if (this.container) { + this.container.resized(); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/source/FlyweightPicker.js b/lib/onyx/source/FlyweightPicker.js new file mode 100644 index 0000000..bb84986 --- /dev/null +++ b/lib/onyx/source/FlyweightPicker.js @@ -0,0 +1,131 @@ +/** + _onyx.FlyweightPicker_, a subkind of onyx.Picker, + is a picker that employs the flyweight pattern. It is used to display a + large list of selectable items. As with + enyo.FlyweightRepeater, + the _onSetupItem_ event allows for customization of item rendering. + + To initialize the FlyweightPicker to a particular value, call _setSelected_ + with the index of the item you wish to select, and call _setContent_ with + the item that should be shown in the activator button. + + FlyweightPicker will send an _onSelect_ event with a selected item's + information. This can be received by a client application to determine which + item was selected. + + enyo.kind({ + handlers: { + onSelect: "itemSelected" + }, + components: [ + {kind: "onyx.PickerDecorator", components: [ + {}, + {name: "yearPicker", kind: "onyx.FlyweightPicker", count: 200, + onSetupItem: "setupYear", components: [ + {name: "year"} + ] + } + ]} + ], + create: function() { + var d = new Date(); + var y = d.getYear(); + this.$.yearPicker.setSelected(y); + this.$.year.setContent(1900+y); + }, + setupYear: function(inSender, inEvent) { + this.$.year.setContent(1900+inEvent.index); + }, + itemSelected: function(inSender, inEvent) { + enyo.log("Picker Item Selected: " + inEvent.selected.content); + } + }) + */ +enyo.kind({ + name: "onyx.FlyweightPicker", + kind: "onyx.Picker", + classes: "onyx-flyweight-picker", + published: { + //* How many rows to render + count: 0 + }, + events: { + /** + Fires when a row is being initialized. The _index_ property contains + the row index, while the _flyweight_ property contains the row + control, for decoration. + */ + onSetupItem: "", + /** + Fires when an item is selected. The _content_ property contains the + content of the selected item, while the _selected_ property contains + its row index. + */ + onSelect: "" + }, + //* @protected + handlers: { + onSelect: "itemSelect" + }, + components: [ + {name: "scroller", kind: "enyo.Scroller", strategyKind: "TouchScrollStrategy", components: [ + {name: "flyweight", kind: "FlyweightRepeater", noSelect: true, ontap: "itemTap"} + ]} + ], + scrollerName: "scroller", + initComponents: function() { + this.controlParentName = 'flyweight'; + this.inherited(arguments); + //Force the flyweight's client control (MenuItem is default) to activate. This will + //result in a call to processActivatedItem which preps our picker selection logic. + //This is a workaround for changes caused by ENYO-1609 which resulted in ENYO-1611. + this.$.flyweight.$.client.children[0].setActive(true); + }, + create: function() { + this.inherited(arguments); + this.countChanged(); + }, + rendered: function() { + this.inherited(arguments); + this.selectedChanged(); + }, + scrollToSelected: function() { + var n = this.$.flyweight.fetchRowNode(this.selected); + this.getScroller().scrollToNode(n, !this.menuUp); + }, + countChanged: function() { + this.$.flyweight.count = this.count; + }, + processActivatedItem: function(inItem) { + this.item = inItem; + }, + selectedChanged: function(inOld) { + if (!this.item) { + return; + } + if (inOld != null) { + this.item.removeClass("selected"); + this.$.flyweight.renderRow(inOld); + } + var n; + if (this.selected != null) { + this.item.addClass("selected"); + this.$.flyweight.renderRow(this.selected); + // need to remove the class from control to make sure it won't apply to other rows + this.item.removeClass("selected"); + n = this.$.flyweight.fetchRowNode(this.selected); + } + this.doChange({selected: this.selected, content: n && n.textContent || this.item.content}); + }, + itemTap: function(inSender, inEvent) { + this.setSelected(inEvent.rowIndex); + //Send the select event that we want the client to receive. + this.doSelect({selected: this.item, content: this.item.content}); + }, + itemSelect: function(inSender, inEvent) { + //Block all select events that aren't coming from this control. This is to prevent select events from MenuItems since they won't have the correct value in a Flyweight context. + if (inEvent.originator != this) { + return true; + } + } +}); diff --git a/lib/onyx/source/Grabber.js b/lib/onyx/source/Grabber.js new file mode 100644 index 0000000..0fd74f5 --- /dev/null +++ b/lib/onyx/source/Grabber.js @@ -0,0 +1,19 @@ +/** + A control styled to indicate that an object can be grabbed and moved. It + should only be used in this limited context--to indicate that dragging the + object will result in movement. + + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Grabber", ondragstart: "grabberDragstart", + ondrag: "grabberDrag", ondragfinish: "grabberDragFinish"}, + {kind: "onyx.Button", content: "More stuff"} + ]} + + When using a Grabber inside a Fittable control, be sure to set "noStretch: true" + on the Fittable or else give it an explicit height. Otherwise, the Grabber + may not be visible. +*/ +enyo.kind({ + name: "onyx.Grabber", + classes: "onyx-grabber" +}); \ No newline at end of file diff --git a/lib/onyx/source/Groupbox.js b/lib/onyx/source/Groupbox.js new file mode 100644 index 0000000..1b41d5b --- /dev/null +++ b/lib/onyx/source/Groupbox.js @@ -0,0 +1,41 @@ +/** + _onyx.Groupbox_ displays rows of controls as a vertically-stacked group. It + is designed to have container controls as its children, with each container + representing a row in the Groupbox. + + A header may be added by specifying an + onyx.GroupboxHeader as the first control + in the Groupbox, e.g.: + + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "Sounds"}, + {components: [ + {content: "System Sounds"}, + {kind: "onyx.ToggleButton", value: true} + ]}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input"} + ]} + ]} + ]} + +*/ +enyo.kind({ + name: "onyx.Groupbox", + classes: "onyx-groupbox" +}); + +/** + A GroupboxHeader is designed to be placed inside an onyx.Groupbox. When a header for a group is desired, + make a GroupboxHeader the first control inside a Groupbox. + + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.GroupboxHeader", content: "Sounds"}, + {content: "Yawn"}, + {content: "Beep"} + ]} +*/ +enyo.kind({ + name: "onyx.GroupboxHeader", + classes: "onyx-groupbox-header" +}); \ No newline at end of file diff --git a/lib/onyx/source/Icon.js b/lib/onyx/source/Icon.js new file mode 100644 index 0000000..d139076 --- /dev/null +++ b/lib/onyx/source/Icon.js @@ -0,0 +1,37 @@ +/** + A control that displays an icon. The icon image is specified by setting the + *src* property to a URL. + + In Onyx, icons have a size of 32x32 pixels. Since the icon image is applied + as a CSS background, the height and width of an icon must be set if an image + of a different size is used. + + {kind: "onyx.Icon", src: "images/search.png"} + + When an icon should act like a button, use an onyx.IconButton. + +*/ +enyo.kind({ + name: "onyx.Icon", + published: { + //* URL specifying path to icon image + src: "", + //* When true, icon is shown as disabled. + disabled: false + }, + classes: "onyx-icon", + //* @protected + create: function() { + this.inherited(arguments); + if (this.src) { + this.srcChanged(); + } + this.disabledChanged(); + }, + disabledChanged: function() { + this.addRemoveClass("disabled", this.disabled); + }, + srcChanged: function() { + this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/IconButton.js b/lib/onyx/source/IconButton.js new file mode 100644 index 0000000..35bf33c --- /dev/null +++ b/lib/onyx/source/IconButton.js @@ -0,0 +1,54 @@ +/** + _onyx.IconButton_ is an icon that acts like a button. The icon image is + specified by setting the _src_ property to a URL. + + If you want to combine an icon with text inside a button, use an + onyx.Icon inside an + onyx.Button. + + The image associated with the _src_ property of the IconButton is assumed + to be 32x64-pixel strip with the top half showing the button's normal state + and the bottom half showing its state when hovered-over or active. + + For more information, see the documentation on + [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer + Guide. +*/ +enyo.kind({ + name: "onyx.IconButton", + kind: "onyx.Icon", + published: { + //* Used when the IconButton is part of a enyo.Group, true + //* to indicate that this is the active button of the group, false otherwise. + active: false + }, + classes: "onyx-icon-button", + //* @protected + create: function() { + //workaround for FirefoxOS which doesn't support :active:hover css selectors + if(enyo.platform.firefoxOS) { + this.handlers.ondown = "down"; + this.handlers.onleave = "leave"; + } + this.inherited(arguments); + }, + down: function(inSender, inEvent) { + this.addClass("pressed"); + }, + leave: function(inSender, inEvent) { + this.removeClass("pressed"); + }, + rendered: function() { + this.inherited(arguments); + this.activeChanged(); + }, + tap: function() { + if (this.disabled) { + return true; + } + this.setActive(true); + }, + activeChanged: function() { + this.bubble("onActivate"); + } +}); diff --git a/lib/onyx/source/Input.js b/lib/onyx/source/Input.js new file mode 100644 index 0000000..8c6ed90 --- /dev/null +++ b/lib/onyx/source/Input.js @@ -0,0 +1,19 @@ +/** + _onyx.Input_ is an Onyx-styled input control, derived from + enyo.Input. Typically, an _onyx.Input_ is placed + inside an onyx.InputDecorator, which + provides styling, e.g.: + + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Enter some text...", onchange: "inputChange"} + ]} + + For more information, see the documentation on + [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "onyx.Input", + kind: "enyo.Input", + classes: "onyx-input" +}); diff --git a/lib/onyx/source/InputDecorator.js b/lib/onyx/source/InputDecorator.js new file mode 100644 index 0000000..bda0e86 --- /dev/null +++ b/lib/onyx/source/InputDecorator.js @@ -0,0 +1,61 @@ +/** + _onyx.InputDecorator_ is a control that provides input styling. Any controls + in the InputDecorator will appear to be inside an area styled as an input. + Usually, an InputDecorator surrounds an onyx.Input. + + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input"} + ]} + + Other controls, such as buttons, may be placed to the right or left of the + input control, e.g.: + + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.IconButton", src: "search.png"}, + {kind: "onyx.Input"}, + {kind: "onyx.IconButton", src: "cancel.png"} + ]} + + Note that the InputDecorator fits around the content inside it. If the + decorator is sized, then its contents will likely need to be sized as well. + + {kind: "onyx.InputDecorator", style: "width: 500px;", components: [ + {kind: "onyx.Input", style: "width: 100%;"} + ]} +*/ +enyo.kind({ + name: "onyx.InputDecorator", + kind: "enyo.ToolDecorator", + tag: "label", + classes: "onyx-input-decorator", + published:{ + //* Set to true to make the input look focused when it's not. + alwaysLooksFocused:false + }, + //* @protected + handlers: { + onDisabledChange: "disabledChange", + onfocus: "receiveFocus", + onblur: "receiveBlur" + }, + create:function() { + this.inherited(arguments); + this.updateFocus(false); + }, + alwaysLooksFocusedChanged:function(oldValue) { + this.updateFocus(this.focus); + }, + updateFocus:function(focus) { + this.focused = focus; + this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); + }, + receiveFocus: function() { + this.updateFocus(true); + }, + receiveBlur: function() { + this.updateFocus(false); + }, + disabledChange: function(inSender, inEvent) { + this.addRemoveClass("onyx-disabled", inEvent.originator.disabled); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/IntegerPicker.js b/lib/onyx/source/IntegerPicker.js new file mode 100644 index 0000000..1e19644 --- /dev/null +++ b/lib/onyx/source/IntegerPicker.js @@ -0,0 +1,78 @@ +/** + _onyx.IntegerPicker_, a subkind of onyx.Picker, + is used to display a list of integers that can be selected, ranging from + _min_ to _max_. It is meant to be used in conjunction with an + onyx.PickerDecorator. The decorator + loosely couples the picker with an + onyx.PickerButton--a button that, when + tapped, shows the picker. Once an item is selected, the list of items + closes, but the item stays selected and the PickerButton displays the choice + that was made. + + To initialize the IntegerPicker to a particular value, set the _value_ + property to the integer that should be selected. + + {kind: "onyx.PickerDecorator", components: [ + {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton + {kind: "onyx.IntegerPicker", min: 0, max: 25, value: 5} + ]} + + Each item in the list is an onyx.MenuItem, so + an application may listen for an _onSelect_ event with the item to determine + which picker item was selected. + + For more information, see the documentation on + Pickers in the + Enyo Developer Guide. + */ +enyo.kind({ + name: "onyx.IntegerPicker", + kind: "onyx.Picker", + published: { + value: 0, + min: 0, + max: 9 + }, + //* @protected + create: function() { + this.inherited(arguments); + this.rangeChanged(); + }, + minChanged: function() { + this.destroyClientControls(); + this.rangeChanged(); + this.render(); + }, + maxChanged: function() { + this.destroyClientControls(); + this.rangeChanged(); + this.render(); + }, + rangeChanged: function() { + for (var i=this.min; i<=this.max; i++) { + this.createComponent({content: i, active: (i===this.value) ? true : false}); + } + }, + valueChanged: function(inOld) { + var controls = this.getClientControls(); + var len = controls.length; + // Validate our value + this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; + for (var i=0; ionyx.Popup that + displays a list of onyx.MenuItem objects and + looks like a popup menu. It is meant to be used in conjunction with an + onyx.MenuDecorator. The decorator couples + the menu with an activating control, which may be a button or any other + control with an _onActivate_ event. When the control is activated, the menu + shows itself in the correct position relative to the activator. + + {kind: "onyx.MenuDecorator", components: [ + {content: "Show menu"}, + {kind: "onyx.Menu", components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "Label", classes: "onyx-menu-label"}, + {content: "3"}, + ]} + ]} + + For more information, see the documentation on + Menus in the Enyo + Developer Guide. + */ +enyo.kind({ + name: "onyx.Menu", + kind: "onyx.Popup", + //* If true, prevents controls outside the menu from receiving events while + //* the menu is showing + modal: true, + defaultKind: "onyx.MenuItem", + classes: "onyx-menu", + published: { + //* Maximum height of the menu + maxHeight: 200, + //* Toggle scrolling + scrolling: true + }, + handlers: { + onActivate: "itemActivated", + onRequestShowMenu: "requestMenuShow", + onRequestHideMenu: "requestHide" + }, + childComponents: [ + {name: "client", kind: "enyo.Scroller", strategyKind: "TouchScrollStrategy"} + ], + showOnTop: false, + scrollerName: "client", + create: function() { + this.inherited(arguments); + this.maxHeightChanged(); + }, + initComponents: function() { + if (this.scrolling) { + this.createComponents(this.childComponents, {isChrome: true}); + } + this.inherited(arguments); + }, + getScroller: function() { + return this.$[this.scrollerName]; + }, + maxHeightChanged: function() { + if (this.scrolling) { + this.getScroller().setMaxHeight(this.maxHeight + "px"); + } + }, + itemActivated: function(inSender, inEvent) { + inEvent.originator.setActive(false); + return true; + }, + showingChanged: function() { + this.inherited(arguments); + if (this.scrolling) { + this.getScroller().setShowing(this.showing); + } + this.adjustPosition(true); + }, + requestMenuShow: function(inSender, inEvent) { + if (this.floating) { + var n = inEvent.activator.hasNode(); + if (n) { + var r = this.activatorOffset = this.getPageOffset(n); + this.applyPosition({top: r.top + (this.showOnTop ? 0 : r.height), left: r.left, width: r.width}); + } + } + this.show(); + return true; + }, + applyPosition: function(inRect) { + var s = ""; + for (var n in inRect) { + s += (n + ":" + inRect[n] + (isNaN(inRect[n]) ? "; " : "px; ")); + } + this.addStyles(s); + }, + getPageOffset: function(inNode) { + // getBoundingClientRect returns top/left values which are relative to the viewport and not absolute + var r = inNode.getBoundingClientRect(); + + // IE8 doesn't return window.page{X/Y}Offset & r.{height/width} + // FIXME: Perhaps use an alternate universal method instead of conditionals + var pageYOffset = (window.pageYOffset === undefined) ? document.documentElement.scrollTop : window.pageYOffset; + var pageXOffset = (window.pageXOffset === undefined) ? document.documentElement.scrollLeft : window.pageXOffset; + var rHeight = (r.height === undefined) ? (r.bottom - r.top) : r.height; + var rWidth = (r.width === undefined) ? (r.right - r.left) : r.width; + + return {top: r.top + pageYOffset, left: r.left + pageXOffset, height: rHeight, width: rWidth}; + }, + //* @protected + /* Adjusts the menu position to fit inside the current window size. + /* Note that we aren't currently adjusting picker scroller heights. + */ + adjustPosition: function() { + if (this.showing && this.hasNode()) { + if (this.scrolling && !this.showOnTop) { + this.getScroller().setMaxHeight(this.maxHeight+"px"); + } + this.removeClass("onyx-menu-up"); + + //reset the left position before we get the bounding rect for proper horizontal calculation + if (!this.floating) { + this.applyPosition({left: "auto"}); + } + + var b = this.node.getBoundingClientRect(); + var bHeight = (b.height === undefined) ? (b.bottom - b.top) : b.height; + var innerHeight = (window.innerHeight === undefined) ? document.documentElement.clientHeight : window.innerHeight; + var innerWidth = (window.innerWidth === undefined) ? document.documentElement.clientWidth : window.innerWidth; + + //position the menu above the activator if it's getting cut off, but only if there's more room above than below + this.menuUp = (b.top + bHeight > innerHeight) && ((innerHeight - b.bottom) < (b.top - bHeight)); + this.addRemoveClass("onyx-menu-up", this.menuUp); + + //if floating, adjust the vertical positioning + if (this.floating) { + var r = this.activatorOffset; + //if the menu doesn't fit below the activator, move it up + if (this.menuUp) { + this.applyPosition({top: (r.top - bHeight + (this.showOnTop ? r.height : 0)), bottom: "auto"}); + } + else { + //if the top of the menu is above the top of the activator and there's room to move it down, do so + if ((b.top < r.top) && (r.top + (this.showOnTop ? 0 : r.height) + bHeight < innerHeight)) + { + this.applyPosition({top: r.top + (this.showOnTop ? 0 : r.height), bottom: "auto"}); + } + } + } + + //adjust the horizontal positioning to keep the menu from being cut off on the right + if ((b.right) > innerWidth) { + if (this.floating){ + this.applyPosition({left:innerWidth-b.width}); + } else { + this.applyPosition({left: -(b.right - innerWidth)}); + } + } + + //finally prevent the menu from being cut off on the left + if (b.left < 0) { + if (this.floating){ + this.applyPosition({left: 0, right:"auto"}); + } else { + //handle the situation where a non-floating menu is right or left aligned + if (this.getComputedStyleValue("right") == "auto"){ + this.applyPosition({left:-b.left}); + } else { + this.applyPosition({right:b.left}); + } + } + } + + //adjust the scroller height based on room available - only doing this for menus currently + if (this.scrolling && !this.showOnTop){ + b = this.node.getBoundingClientRect(); //update to the current menu position + var scrollerHeight; + if (this.menuUp){ + scrollerHeight = (this.maxHeight < b.bottom) ? this.maxHeight : b.bottom; + } else { + scrollerHeight = ((b.top + this.maxHeight) < innerHeight) ? this.maxHeight : (innerHeight - b.top); + } + this.getScroller().setMaxHeight(scrollerHeight+"px"); + } + } + }, + resizeHandler: function() { + this.inherited(arguments); + this.adjustPosition(); + }, + requestHide: function(){ + this.setShowing(false); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/MenuDecorator.js b/lib/onyx/source/MenuDecorator.js new file mode 100644 index 0000000..631bcb1 --- /dev/null +++ b/lib/onyx/source/MenuDecorator.js @@ -0,0 +1,62 @@ +/** + A control that activates an onyx.Menu. It loosely + couples the Menu with an activating control, which may be a button or any + other control with an _onActivate_ event. The decorator must surround both + the activating control and the menu itself. When the control is activated, + the menu shows itself in the correct position relative to the activator. + + {kind: "onyx.MenuDecorator", components: [ + {content: "Show menu"}, + {kind: "onyx.Menu", components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "Label", classes: "onyx-menu-label"}, + {content: "3"}, + ]} + ]} + */ +enyo.kind({ + name: "onyx.MenuDecorator", + kind: "onyx.TooltipDecorator", + defaultKind: "onyx.Button", + // selection on ios prevents tap events, so avoid. + classes: "onyx-popup-decorator enyo-unselectable", + //* @protected + handlers: { + onActivate: "activated", + onHide: "menuHidden" + }, + activated: function(inSender, inEvent) { + this.requestHideTooltip(); + if (inEvent.originator.active) { + this.menuActive = true; + this.activator = inEvent.originator; + this.activator.addClass("active"); + this.requestShowMenu(); + } + }, + requestShowMenu: function() { + this.waterfallDown("onRequestShowMenu", {activator: this.activator}); + }, + requestHideMenu: function() { + this.waterfallDown("onRequestHideMenu"); + }, + menuHidden: function() { + this.menuActive = false; + if (this.activator) { + this.activator.setActive(false); + this.activator.removeClass("active"); + } + }, + enter: function(inSender) { + if (!this.menuActive) { + this.inherited(arguments); + } + }, + leave: function(inSender, inEvent) { + if (!this.menuActive) { + this.inherited(arguments); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/source/MenuItem.js b/lib/onyx/source/MenuItem.js new file mode 100644 index 0000000..a7b90a4 --- /dev/null +++ b/lib/onyx/source/MenuItem.js @@ -0,0 +1,66 @@ +/** + _MenuItem_ is a button styled to look like a menu item, intended for use in + an onyx.Menu. When the MenuItem is tapped, it + tells the menu to hide itself and sends an _onSelect_ event with its + content and a reference to itself. This event and its properties may be + received by a client application to determine which menu item was selected. + + enyo.kind({ + handlers: { + onSelect: "itemSelected" + }, + components: [ + {kind: "onyx.MenuDecorator", components: [ + {content: "Open Menu (floating)"}, + {kind: "onyx.Menu", floating: true, components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "Label", classes: "onyx-menu-label"}, + {content: "3"}, + ]} + ]} + ], + itemSelected: function(inSender, inEvent) { + enyo.log("Menu Item Selected: " + inEvent.originator.content); + } + }) + */ +enyo.kind({ + name: "onyx.MenuItem", + kind: "enyo.Button", + events: { + /** + Fires when the menu item is selected. + + _inEvent.selected_ contains a reference to the menu item. + + _inEvent.content_ contains the menu item's content. + */ + onSelect: "", + /** + Fires when the content of an item changes. + + _inEvent.content_ contains the content of the item. + */ + onItemContentChange: "" + }, + //* @protected + classes: "onyx-menu-item", + tag: "div", + create: function(){ + this.inherited(arguments); + if (this.active){ + this.bubble("onActivate"); + } + }, + tap: function(inSender) { + this.inherited(arguments); + this.bubble("onRequestHideMenu"); + this.doSelect({selected:this, content:this.content}); + }, + contentChanged: function(inOld){ + this.inherited(arguments); + this.doItemContentChange({content: this.content}); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/MoreToolbar.js b/lib/onyx/source/MoreToolbar.js new file mode 100644 index 0000000..8a66470 --- /dev/null +++ b/lib/onyx/source/MoreToolbar.js @@ -0,0 +1,156 @@ +/** + _onyx.MoreToolbar_ extends enyo.Control, + providing a toolbar that can adapt to different screen sizes by moving + overflowing controls and content into an onyx.Menu. + + {kind: "onyx.MoreToolbar", components: [ + {content: "More Toolbar", unmoveable: true}, + {kind: "onyx.Button", content: "Alpha"}, + {kind: "onyx.Button", content: "Beta"}, + {kind: "onyx.Button", content: "Gamma", unmoveable: true}, + {kind: "onyx.Button", content: "Epsilon"} + ]}, + + You may prevent a control from being moved into the menu by setting its + _unmoveable_ property to true (the default is false). + + For more information, see the documentation on + Toolbars in the + Enyo Developer Guide. +*/ + +enyo.kind({ + name: "onyx.MoreToolbar", + //* @public + classes: "onyx-toolbar onyx-more-toolbar", + //* Style class to be applied to the menu + menuClass: "", + //* Style class to be applied to individual controls moved from the toolbar to the menu + movedClass: "", + //* @protected + layoutKind: "FittableColumnsLayout", + noStretch: true, + handlers: { + onHide: "reflow" + }, + published: { + //* Layout kind that will be applied to the client controls. + clientLayoutKind: "FittableColumnsLayout" + }, + tools: [ + {name: "client", noStretch:true, fit: true, classes: "onyx-toolbar-inline"}, + {name: "nard", kind: "onyx.MenuDecorator", showing: false, onActivate: "activated", components: [ + {kind: "onyx.IconButton", classes: "onyx-more-button"}, + {name: "menu", kind: "onyx.Menu", scrolling:false, classes: "onyx-more-menu"} + ]} + ], + initComponents: function() { + if(this.menuClass && this.menuClass.length>0 && !this.$.menu.hasClass(this.menuClass)) { + this.$.menu.addClass(this.menuClass); + } + this.createChrome(this.tools); + this.inherited(arguments); + this.$.client.setLayoutKind(this.clientLayoutKind); + }, + clientLayoutKindChanged: function(){ + this.$.client.setLayoutKind(this.clientLayoutKind); + }, + reflow: function() { + this.inherited(arguments); + if (this.isContentOverflowing()) { + this.$.nard.show(); + if (this.popItem()) { + this.reflow(); + } + } else if (this.tryPushItem()) { + this.reflow(); + } else if (!this.$.menu.children.length) { + this.$.nard.hide(); + this.$.menu.hide(); + } + }, + activated: function(inSender, inEvent) { + this.addRemoveClass("active",inEvent.originator.active); + }, + popItem: function() { + var c = this.findCollapsibleItem(); + if (c) { + //apply movedClass is needed + if(this.movedClass && this.movedClass.length>0 && !c.hasClass(this.movedClass)) { + c.addClass(this.movedClass); + } + // passing null to add child to the front of the control list + this.$.menu.addChild(c, null); + var p = this.$.menu.hasNode(); + if (p && c.hasNode()) { + c.insertNodeInParent(p); + } + return true; + } + }, + pushItem: function() { + var c$ = this.$.menu.children; + var c = c$[0]; + if (c) { + //remove any applied movedClass + if(this.movedClass && this.movedClass.length>0 && c.hasClass(this.movedClass)) { + c.removeClass(this.movedClass); + } + this.$.client.addChild(c); + var p = this.$.client.hasNode(); + if (p && c.hasNode()) { + var nextChild; + var currIndex; + for(var i=0; i this.$.client.node.clientWidth); + return ((n.offsetLeft + n.offsetWidth) > this.$.client.node.clientWidth); + } + } + }, + findCollapsibleItem: function() { + var c$ = this.$.client.children; + for (var i=c$.length-1; (c=c$[i]); i--) { + if (!c.unmoveable) { + return c; + } else { + if(c.toolbarIndex===undefined) { + c.toolbarIndex = i; + } + } + } + } +}); diff --git a/lib/onyx/source/Picker.js b/lib/onyx/source/Picker.js new file mode 100644 index 0000000..4cd1e9f --- /dev/null +++ b/lib/onyx/source/Picker.js @@ -0,0 +1,103 @@ +/** + _onyx.Picker_, a subkind of onyx.Menu, is used to + display a list of items that can be selected. It is meant to be used in + conjunction with an onyx.PickerDecorator. + The decorator loosely couples the picker with an + onyx.PickerButton--a button that, when + tapped, shows the picker. Once an item is selected, the list of items closes, + but the item stays selected and the PickerButton displays the choice that + was made. + + To initialize the Picker to a particular value, set the _active_ property to + true for the item that should be selected. + + {kind: "onyx.PickerDecorator", components: [ + {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton + {kind: "onyx.Picker", components: [ + {content: "Gmail", active: true}, + {content: "Yahoo"}, + {content: "Outlook"}, + {content: "Hotmail"} + ]} + ]} + + Each item in the list is an onyx.MenuItem, so + an _onSelect_ event with the item can be listened to by a client application + to determine which picker item was selected. + + For more information, see the documentation on + Pickers in the + Enyo Developer Guide. + */ +enyo.kind({ + name: "onyx.Picker", + kind: "onyx.Menu", + classes: "onyx-picker enyo-unselectable", + published: { + //* Currently selected item, if any + selected: null + }, + events: { + /** + Fires when the currently selected item changes. + + _inEvent.selected_ contains the currently selected item. + + _inEvent.content_ contains the content of the currently selected item. + */ + onChange: "" + }, + handlers: { + onItemContentChange: 'itemContentChange' + }, + /** + Set to true to render the picker in a floating layer outside of other + controls. This can be used to guarantee that the picker will be shown + on top of other controls. + */ + floating: true, + //* @protected + // overrides default value from onyx.Menu + showOnTop: true, + initComponents: function() { + this.setScrolling(true); + this.inherited(arguments); + }, + showingChanged: function() { + this.getScroller().setShowing(this.showing); + this.inherited(arguments); + if (this.showing && this.selected) { + this.scrollToSelected(); + } + }, + scrollToSelected: function() { + this.getScroller().scrollToControl(this.selected, !this.menuUp); + }, + itemActivated: function(inSender, inEvent) { + this.processActivatedItem(inEvent.originator); + return this.inherited(arguments); + }, + processActivatedItem: function(inItem) { + if (inItem.active) { + this.setSelected(inItem); + } + }, + selectedChanged: function(inOld) { + if (inOld) { + inOld.removeClass("selected"); + } + if (this.selected) { + this.selected.addClass("selected"); + this.doChange({selected: this.selected, content: this.selected.content}); + } + }, + itemContentChange: function(inSender, inEvent){ + if(inEvent.originator == this.selected){ + this.doChange({selected: this.selected, content: this.selected.content}); + } + }, + resizeHandler: function() { + this.inherited(arguments); + this.adjustPosition(); + } +}); diff --git a/lib/onyx/source/PickerButton.js b/lib/onyx/source/PickerButton.js new file mode 100644 index 0000000..f1c9d14 --- /dev/null +++ b/lib/onyx/source/PickerButton.js @@ -0,0 +1,22 @@ +/** + _onyx.PickerButton_ is a button that, when tapped, shows an + onyx.Picker. Once an item is selected, the list + of items closes, but the item stays selected and the PickerButton displays + the choice that was made. + + For more information, see the documentation on + [Pickers](https://github.com/enyojs/enyo/wiki/Pickers) in the Enyo Developer + Guide. + */ +enyo.kind({ + name: "onyx.PickerButton", + kind: "onyx.Button", + handlers: { + onChange: "change" + }, + change: function(inSender, inEvent) { + if (inEvent.content !== undefined){ + this.setContent(inEvent.content); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/source/PickerDecorator.js b/lib/onyx/source/PickerDecorator.js new file mode 100644 index 0000000..bf248d9 --- /dev/null +++ b/lib/onyx/source/PickerDecorator.js @@ -0,0 +1,30 @@ +/** + A control that activates an onyx.Picker. It + loosely couples the Picker with an activating + onyx.PickerButton. The decorator must + surround both the activating button and the picker itself. When the button + is activated, the picker shows itself in the correct position relative to + the activator. + + {kind: "onyx.PickerDecorator", components: [ + {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton + {kind: "onyx.Picker", components: [ + {content: "Gmail", active: true}, + {content: "Yahoo"}, + {content: "Outlook"}, + {content: "Hotmail"} + ]} + ]} + */ +enyo.kind({ + name: "onyx.PickerDecorator", + kind: "onyx.MenuDecorator", + classes: "onyx-picker-decorator", + defaultKind: "onyx.PickerButton", + handlers: { + onChange: "change" + }, + change: function(inSender, inEvent) { + this.waterfallDown("onChange", inEvent); + } +}); diff --git a/lib/onyx/source/Popup.js b/lib/onyx/source/Popup.js new file mode 100644 index 0000000..cb40ef5 --- /dev/null +++ b/lib/onyx/source/Popup.js @@ -0,0 +1,93 @@ +/** + _onyx.Popup_ is an enhanced [enyo.Popup](http://enyojs.com/api/#enyo.Popup) + with built-in scrim and z-index handling. + + To avoid obscuring popup contents, scrims require the dialog to be floating; + otherwise, they won't render. A modal popup will get a transparent scrim + unless the popup isn't floating. To get a translucent scrim when modal, + specify _scrim: true, scrimWhenModal: false_. + + For more information, see the documentation on + [Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer + Guide. +*/ +enyo.kind({ + name: "onyx.Popup", + kind: "Popup", + classes: "onyx-popup", + published: { + /** + Determines whether a scrim will appear when the dialog is modal. + Note that modal scrims are transparent, so you won't see them. + */ + scrimWhenModal: true, + //* Determines whether or not to display a scrim. Only displays scrims + //* when floating. + scrim: false, + /** + Optional class name to apply to the scrim. Be aware that the scrim + is a singleton and you will be modifying the scrim instance used for + other popups. + */ + scrimClassName: "" + }, + //* @protected + statics: { count: 0 }, + defaultZ: 120, + showingChanged: function() { + if(this.showing) { + onyx.Popup.count++; + this.applyZIndex(); + } + else { + if(onyx.Popup.count > 0) { + onyx.Popup.count--; + } + } + this.showHideScrim(this.showing); + this.inherited(arguments); + }, + showHideScrim: function(inShow) { + if (this.floating && (this.scrim || (this.modal && this.scrimWhenModal))) { + var scrim = this.getScrim(); + if (inShow) { + // move scrim to just under the popup to obscure rest of screen + var i = this.getScrimZIndex(); + this._scrimZ = i; + scrim.showAtZIndex(i); + } else { + scrim.hideAtZIndex(this._scrimZ); + } + enyo.call(scrim, "addRemoveClass", [this.scrimClassName, scrim.showing]); + } + }, + getScrimZIndex: function() { + // Position scrim directly below popup + return this.findZIndex()-1; + }, + getScrim: function() { + // show a transparent scrim for modal popups if scrimWhenModal is true + // if scrim is true, then show a regular scrim. + if (this.modal && this.scrimWhenModal && !this.scrim) { + return onyx.scrimTransparent.make(); + } + return onyx.scrim.make(); + }, + applyZIndex: function() { + // Adjust the zIndex so that popups will properly stack on each other. + this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1; + // leave room for scrim + this.applyStyle("z-index", this._zIndex); + }, + findZIndex: function() { + // a default z value + var z = this.defaultZ; + if (this._zIndex) { + z = this._zIndex; + } else if (this.hasNode()) { + // Re-use existing zIndex if it has one + z = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || z; + } + return (this._zIndex = z); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/ProgressBar.js b/lib/onyx/source/ProgressBar.js new file mode 100644 index 0000000..084e317 --- /dev/null +++ b/lib/onyx/source/ProgressBar.js @@ -0,0 +1,104 @@ +/** + _onyx.ProgressBar_ is a control that shows the current progress of a + process in a horizontal bar. + + {kind: "onyx.ProgressBar", progress: 10} + + To animate progress changes, call the _animateProgressTo_ method: + + this.$.progressBar.animateProgressTo(50); + + You may customize the color of the bar by applying a style via the + _barClasses_ property, e.g.: + + {kind: "onyx.ProgressBar", barClasses: "onyx-dark"} + + For more information, see the documentation on + Progress Indicators + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.ProgressBar", + classes: "onyx-progress-bar", + published: { + //* Current position of progress bar + progress: 0, + //* Minimum progress value (i.e., no progress made) + min: 0, + //* Maximum progress value (i.e., process complete) + max: 100, + //* CSS classes to apply to progress bar + barClasses: "", + //* If true, stripes are shown in progress bar + showStripes: true, + //* If true (and _showStripes_ is true), stripes shown in progress bar + //* are animated + animateStripes: true, + //* Value increment that a sliders can be "snapped to" in either direction + increment: 0 + }, + events: { + //* Fires when progress bar finishes animating to a position. + onAnimateProgressFinish: "" + }, + //* @protected + components: [ + {name: "progressAnimator", kind: "Animator", onStep: "progressAnimatorStep", onEnd: "progressAnimatorComplete"}, + {name: "bar", classes: "onyx-progress-bar-bar"} + ], + create: function() { + this.inherited(arguments); + this.progressChanged(); + this.barClassesChanged(); + this.showStripesChanged(); + this.animateStripesChanged(); + }, + barClassesChanged: function(inOld) { + this.$.bar.removeClass(inOld); + this.$.bar.addClass(this.barClasses); + }, + showStripesChanged: function() { + this.$.bar.addRemoveClass("striped", this.showStripes); + }, + animateStripesChanged: function() { + this.$.bar.addRemoveClass("animated", this.animateStripes); + }, + progressChanged: function() { + this.progress = this.clampValue(this.min, this.max, this.progress); + var p = this.calcPercent(this.progress); + this.updateBarPosition(p); + }, + calcIncrement: function(inValue) { + return (Math.round(inValue / this.increment) * this.increment); + }, + clampValue: function(inMin, inMax, inValue) { + return Math.max(inMin, Math.min(inValue, inMax)); + }, + calcRatio: function(inValue) { + return (inValue - this.min) / (this.max - this.min); + }, + calcPercent: function(inValue) { + return this.calcRatio(inValue) * 100; + }, + updateBarPosition: function(inPercent) { + this.$.bar.applyStyle("width", inPercent + "%"); + }, + //* @public + //* Animates progress to the given value. + animateProgressTo: function(inValue) { + this.$.progressAnimator.play({ + startValue: this.progress, + endValue: inValue, + node: this.hasNode() + }); + }, + //* @protected + progressAnimatorStep: function(inSender) { + this.setProgress(inSender.value); + return true; + }, + progressAnimatorComplete: function(inSender) { + this.doAnimateProgressFinish(inSender); + return true; + } +}); diff --git a/lib/onyx/source/ProgressButton.js b/lib/onyx/source/ProgressButton.js new file mode 100644 index 0000000..8bbef24 --- /dev/null +++ b/lib/onyx/source/ProgressButton.js @@ -0,0 +1,33 @@ +/** + _onyx.ProgressButton_ is a progress bar that has a cancel button on the + right and may have other controls inside of it. + + {kind: "onyx.ProgressButton"}, + {kind: "onyx.ProgressButton", barClasses: "onyx-light", progress: 20, components: [ + {content: "0"}, + {content: "100", style: "float: right;"} + ]} + + For more information, see the documentation on + Progress Indicators + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.ProgressButton", + kind: "onyx.ProgressBar", + classes: "onyx-progress-button", + events: { + //* Fires when cancel button is tapped. + onCancel: "" + }, + //* @protected + components: [ + {name: "progressAnimator", kind: "Animator", onStep: "progressAnimatorStep", onEnd: "progressAnimatorComplete"}, + {name: "bar", classes: "onyx-progress-bar-bar onyx-progress-button-bar"}, + {name: "client", classes: "onyx-progress-button-client"}, + {kind: "onyx.Icon", src: "$lib/onyx/images/progress-button-cancel.png", classes: "onyx-progress-button-icon", ontap: "cancelTap"} + ], + cancelTap: function() { + this.doCancel(); + } +}); diff --git a/lib/onyx/source/RadioButton.js b/lib/onyx/source/RadioButton.js new file mode 100644 index 0000000..590cb0d --- /dev/null +++ b/lib/onyx/source/RadioButton.js @@ -0,0 +1,13 @@ +/** + A radio button designed for use within an + onyx.RadioGroup. + + For more information, see the documentation on + [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer + Guide. +*/ +enyo.kind({ + name: "onyx.RadioButton", + kind: "Button", + classes: "onyx-radiobutton" +}); diff --git a/lib/onyx/source/RadioGroup.js b/lib/onyx/source/RadioGroup.js new file mode 100644 index 0000000..fa7b8a3 --- /dev/null +++ b/lib/onyx/source/RadioGroup.js @@ -0,0 +1,20 @@ +/** + A group of onyx.RadioButton objects + laid out horizontally. Within the same radio group, tapping on one radio button + will release any previously tapped radio button. + + {kind: "onyx.RadioGroup", components: [ + {content: "foo", active: true}, + {content: "bar"}, + {content: "baz"} + ]} +*/ +enyo.kind({ + name: "onyx.RadioGroup", + kind: "Group", + defaultKind: "onyx.RadioButton", + //* @protected + // set to true to provide radio button behavior + highlander: true +}); + diff --git a/lib/onyx/source/RangeSlider.js b/lib/onyx/source/RangeSlider.js new file mode 100644 index 0000000..933bc44 --- /dev/null +++ b/lib/onyx/source/RangeSlider.js @@ -0,0 +1,227 @@ +/** + _onyx.RangeSlider_ is a control that combines a horizontal slider with two + control knobs. The user may drag the knobs to select a desired range of + values. + + {kind: "onyx.RangeSlider", rangeMin: 100, rangeMax: 500, + rangeStart: 200, rangeEnd: 400, interval: 20} + + _onChanging_ events are fired while the control knobs are being dragged, and + an _onChange_ event is fired when the position is set by finishing a drag. +*/ +enyo.kind({ + name: "onyx.RangeSlider", + kind: "onyx.ProgressBar", + classes: "onyx-slider", + published: { + //* @public + //* Minimum slider value + rangeMin: 0, + //* Maximum slider value + rangeMax: 100, + /** + Value of first slider, expressed as an integer between _rangeMin_ + and _rangeMax_ + */ + rangeStart: 0, + /** + Value of second slider, expressed as an integer between _rangeMin_ + and _rangeMax_ + */ + rangeEnd: 100, + //* @protected + // Position of first slider, expressed as an integer between 0 and 100 (percentage) + beginValue: 0, + // Position of second slider, expressed as an integer between 0 and 100 (percentage) + endValue: 0 + }, + //* @public + events: { + /** + Fires when bar position is set. + + _inEvent.value_ contains the new position. + + _inEvent.startChanged_ is a boolean value indicating whether the + first slider (_rangeStart_) triggered the event. + */ + onChange: "", + /** + Fires while control knob is being dragged. + + _inEvent.value_ contains the current position. + */ + onChanging: "" + }, + //* If true, stripes are shown in the slider bar + showStripes: false, + //* If true, labels are shown above each slider knob + showLabels: false, + //* @protected + handlers: { + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish", + ondown: "down" + }, + moreComponents: [ + {name: "startKnob", classes: "onyx-slider-knob"}, + {name: "endKnob", classes: "onyx-slider-knob onyx-range-slider-knob"} + ], + create: function() { + this.inherited(arguments); + this.createComponents(this.moreComponents); + this.initControls(); + }, + rendered: function() { + this.inherited(arguments); + var p = this.calcPercent(this.beginValue); + this.updateBarPosition(p); + }, + initControls: function() { + this.$.bar.applyStyle("position", "relative"); + this.refreshRangeSlider(); + if (this.showLabels) { + this.$.startKnob.createComponent({name: "startLabel", kind: "onyx.RangeSliderKnobLabel"}); + this.$.endKnob.createComponent({name: "endLabel", kind: "onyx.RangeSliderKnobLabel"}); + } + }, + refreshRangeSlider: function() { + // Calculate range percentages, in order to position sliders + this.beginValue = this.calcKnobPercent(this.rangeStart); + this.endValue = this.calcKnobPercent(this.rangeEnd); + this.beginValueChanged(); + this.endValueChanged(); + }, + calcKnobRatio: function(inValue) { + return (inValue - this.rangeMin) / (this.rangeMax - this.rangeMin); + }, + calcKnobPercent: function(inValue) { + return this.calcKnobRatio(inValue) * 100; + }, + beginValueChanged: function(sliderPos) { + if (sliderPos === undefined) { + var p = this.calcPercent(this.beginValue); + this.updateKnobPosition(p, this.$.startKnob); + } + }, + endValueChanged: function(sliderPos) { + if (sliderPos === undefined) { + var p = this.calcPercent(this.endValue); + this.updateKnobPosition(p, this.$.endKnob); + } + }, + calcKnobPosition: function(inEvent) { + var x = inEvent.clientX - this.hasNode().getBoundingClientRect().left; + return (x / this.getBounds().width) * (this.max - this.min) + this.min; + }, + updateKnobPosition: function(inPercent, inControl) { + inControl.applyStyle("left", inPercent + "%"); + this.updateBarPosition(); + }, + updateBarPosition: function() { + if ((this.$.startKnob !== undefined) && (this.$.endKnob !== undefined)) { + var barStart = this.calcKnobPercent(this.rangeStart); + var barWidth = this.calcKnobPercent(this.rangeEnd) - barStart; + this.$.bar.applyStyle("left", barStart + "%"); + this.$.bar.applyStyle("width", barWidth + "%"); + } + }, + calcRangeRatio: function(inValue) { + return ((inValue / 100) * (this.rangeMax - this.rangeMin) + this.rangeMin) - (this.increment/2); + }, + swapZIndex: function(inControl) { + if (inControl === "startKnob") { + this.$.startKnob.applyStyle("z-index", 1); + this.$.endKnob.applyStyle("z-index", 0); + } else if (inControl === "endKnob") { + this.$.startKnob.applyStyle("z-index", 0); + this.$.endKnob.applyStyle("z-index", 1); + } + }, + down: function(inSender, inEvent) { + this.swapZIndex(inSender.name); + }, + dragstart: function(inSender, inEvent) { + if (inEvent.horizontal) { + inEvent.preventDefault(); + this.dragging = true; + return true; + } + }, + drag: function(inSender, inEvent) { + if (this.dragging) { + var knobPos = this.calcKnobPosition(inEvent); + var _val, val, p; + + if ((inSender.name === "startKnob") && (knobPos >= 0)) { + if (((knobPos <= this.endValue) && (inEvent.xDirection === -1)) || (knobPos <= this.endValue)) { + this.setBeginValue(knobPos); + _val = this.calcRangeRatio(this.beginValue); + val = (this.increment) ? this.calcIncrement(_val+0.5*this.increment) : _val; + p = this.calcKnobPercent(val); + this.updateKnobPosition(p, this.$.startKnob); + this.setRangeStart(val); + this.doChanging({value: val}); + } else { + return this.drag(this.$.endKnob, inEvent); + } + } else if ((inSender.name === "endKnob") && (knobPos <= 100)) { + if (((knobPos >= this.beginValue) && (inEvent.xDirection === 1)) || (knobPos >= this.beginValue)) { + this.setEndValue(knobPos); + _val = this.calcRangeRatio(this.endValue); + val = (this.increment) ? this.calcIncrement(_val+0.5*this.increment) : _val; + p = this.calcKnobPercent(val); + this.updateKnobPosition(p, this.$.endKnob); + this.setRangeEnd(val); + this.doChanging({value: val}); + } else { + return this.drag(this.$.startKnob, inEvent); + } + } + return true; + } + }, + dragfinish: function(inSender, inEvent) { + this.dragging = false; + inEvent.preventTap(); + var val; + if (inSender.name === "startKnob") { + val = this.calcRangeRatio(this.beginValue); + this.doChange({value: val, startChanged: true}); + } else if (inSender.name === "endKnob") { + val = this.calcRangeRatio(this.endValue); + this.doChange({value: val, startChanged: false}); + } + return true; + }, + rangeMinChanged: function() { + this.refreshRangeSlider(); + }, + rangeMaxChanged: function() { + this.refreshRangeSlider(); + }, + rangeStartChanged: function() { + this.refreshRangeSlider(); + }, + rangeEndChanged: function() { + this.refreshRangeSlider(); + }, + setStartLabel: function(inContent) { + this.$.startKnob.waterfallDown("onSetLabel", inContent); + }, + setEndLabel: function(inContent) { + this.$.endKnob.waterfallDown("onSetLabel", inContent); + } +}); + +enyo.kind({ + name: "onyx.RangeSliderKnobLabel", + classes: "onyx-range-slider-label", + handlers: { + onSetLabel: "setLabel" + }, + setLabel: function(inSender, inContent) { + this.setContent(inContent); + } +}); diff --git a/lib/onyx/source/RichText.js b/lib/onyx/source/RichText.js new file mode 100644 index 0000000..86a674b --- /dev/null +++ b/lib/onyx/source/RichText.js @@ -0,0 +1,19 @@ +/** + _onyx.RichText_ is an Onyx-styled RichText control, derived from + enyo.RichText. Typically, an _onyx.RichText_ + is placed inside an onyx.InputDecorator, + which provides styling, e.g.: + + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.RichText", style: "width: 100px;", onchange: "inputChange"} + ]} + + For more information, see the documentation on + [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "onyx.RichText", + kind: "enyo.RichText", + classes: "onyx-richtext" +}); diff --git a/lib/onyx/source/Scrim.js b/lib/onyx/source/Scrim.js new file mode 100644 index 0000000..fc12ded --- /dev/null +++ b/lib/onyx/source/Scrim.js @@ -0,0 +1,114 @@ +/** + _onyx.Scrim_ provides an overlay that will prevent taps from propagating to + the controls that it covers. A scrim may be "floating" or "non-floating". A + floating scrim will fill the entire viewport, while a non-floating scrim + will be constrained by the dimensions of its container. + + The scrim should have a CSS class of _"onyx-scrim-transparent"_, + _"onyx-scrim-translucent"_, or any other class that has + _"pointer-events: auto"_ in its style properties. + + You may specify the z-index at which you want the scrim to appear by calling + _showAtZIndex_; if you do so, you must call _hideAtZIndex_ with the same + value to hide the scrim. +*/ + +enyo.kind({ + name: "onyx.Scrim", + //* Current visibility state of scrim + showing: false, + classes: "onyx-scrim enyo-fit", + /** + If true, scrim is rendered in a floating layer outside of other + controls. This can be used to guarantee that the scrim will be shown + on top of other controls. + */ + floating: false, + //* @protected + create: function() { + this.inherited(arguments); + this.zStack = []; + if (this.floating) { + this.setParent(enyo.floatingLayer); + } + }, + showingChanged: function() { + // auto render when shown. + if (this.floating && this.showing && !this.hasNode()) { + this.render(); + } + this.inherited(arguments); + //this.addRemoveClass(this.showingClassName, this.showing); + }, + //* @protected + addZIndex: function(inZIndex) { + if (enyo.indexOf(inZIndex, this.zStack) < 0) { + this.zStack.push(inZIndex); + } + }, + removeZIndex: function(inControl) { + enyo.remove(inControl, this.zStack); + }, + //* @public + //* Shows scrim at the specified z-index. Note: If you use _showAtZIndex_, + //* you must call _hideAtZIndex_ to properly unwind the z-index stack. + showAtZIndex: function(inZIndex) { + this.addZIndex(inZIndex); + if (inZIndex !== undefined) { + this.setZIndex(inZIndex); + } + this.show(); + }, + //* Hides scrim at the specified z-index. + hideAtZIndex: function(inZIndex) { + this.removeZIndex(inZIndex); + if (!this.zStack.length) { + this.hide(); + } else { + var z = this.zStack[this.zStack.length-1]; + this.setZIndex(z); + } + }, + //* @protected + // Set scrim to show at `inZIndex` + setZIndex: function(inZIndex) { + this.zIndex = inZIndex; + this.applyStyle("z-index", inZIndex); + }, + make: function() { + return this; + } +}); + +//* @protected +// +// Scrim singleton exposing a subset of Scrim API; +// is replaced with a proper enyo.Scrim instance. +// +enyo.kind({ + name: "onyx.scrimSingleton", + kind: null, + constructor: function(inName, inProps) { + this.instanceName = inName; + enyo.setObject(this.instanceName, this); + this.props = inProps || {}; + }, + make: function() { + var s = new onyx.Scrim(this.props); + enyo.setObject(this.instanceName, s); + return s; + }, + showAtZIndex: function(inZIndex) { + var s = this.make(); + s.showAtZIndex(inZIndex); + }, + // in case somebody does this out of order + hideAtZIndex: enyo.nop, + show: function() { + var s = this.make(); + s.show(); + } +}); + +new onyx.scrimSingleton("onyx.scrim", {floating: true, classes: "onyx-scrim-translucent"}); +new onyx.scrimSingleton("onyx.scrimTransparent", {floating: true, classes: "onyx-scrim-transparent"}); diff --git a/lib/onyx/source/Slider.js b/lib/onyx/source/Slider.js new file mode 100644 index 0000000..0fccedc --- /dev/null +++ b/lib/onyx/source/Slider.js @@ -0,0 +1,136 @@ +/** + _onyx.Slider_ is a control that presents a range of selection options in the + form of a horizontal slider with a control knob. The knob may be tapped and + dragged to the desired location. + + {kind: "onyx.Slider", value: 30} + + _onChanging_ events are fired while the control knob is being dragged, and + an _onChange_ event is fired when the position is set, either by finishing a + drag or by tapping the bar. + + For more information, see the documentation on + Progress Indicators + in the Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.Slider", + kind: "onyx.ProgressBar", + classes: "onyx-slider", + published: { + //* Position of slider, expressed as an integer between 0 and 100, + //* inclusive + value: 0, + //* If true, current progress will be styled differently from rest of bar + lockBar: true, + //* If true, tapping on bar will change current position + tappable: true + }, + events: { + //* Fires when bar position is set. The _value_ property contains the + //* new position. + onChange: "", + //* Fires while control knob is being dragged. The _value_ property + //* contains the current position. + onChanging: "", + //* Fires when animation to a position finishes. + onAnimateFinish: "" + }, + //* If true, stripes are shown in the slider bar + showStripes: false, + //* @protected + handlers: { + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish" + }, + moreComponents: [ + {kind: "Animator", onStep: "animatorStep", onEnd: "animatorComplete"}, + {classes: "onyx-slider-taparea"}, + {name: "knob", classes: "onyx-slider-knob"} + ], + create: function() { + this.inherited(arguments); + //workaround for FirefoxOS which doesn't support :active:hover css selectors + if(enyo.platform.firefoxOS) { + this.moreComponents[2].ondown = "down"; + this.moreComponents[2].onleave = "leave"; + } + this.createComponents(this.moreComponents); + this.valueChanged(); + }, + valueChanged: function() { + this.value = this.clampValue(this.min, this.max, this.value); + var p = this.calcPercent(this.value); + this.updateKnobPosition(p); + if (this.lockBar) { + this.setProgress(this.value); + } + }, + updateKnobPosition: function(inPercent) { + this.$.knob.applyStyle("left", inPercent + "%"); + }, + calcKnobPosition: function(inEvent) { + var x = inEvent.clientX - this.hasNode().getBoundingClientRect().left; + return (x / this.getBounds().width) * (this.max - this.min) + this.min; + }, + dragstart: function(inSender, inEvent) { + if (inEvent.horizontal) { + inEvent.preventDefault(); + this.dragging = true; + return true; + } + }, + drag: function(inSender, inEvent) { + if (this.dragging) { + var v = this.calcKnobPosition(inEvent); + v = (this.increment) ? this.calcIncrement(v) : v; + this.setValue(v); + this.doChanging({value: this.value}); + return true; + } + }, + dragfinish: function(inSender, inEvent) { + this.dragging = false; + inEvent.preventTap(); + this.doChange({value: this.value}); + return true; + }, + tap: function(inSender, inEvent) { + if (this.tappable) { + var v = this.calcKnobPosition(inEvent); + v = (this.increment) ? this.calcIncrement(v) : v; + this.tapped = true; + this.animateTo(v); + return true; + } + }, + down: function(inSender, inEvent) { + this.addClass("pressed"); + }, + leave: function(inSender, inEvent) { + this.removeClass("pressed"); + }, + //* @public + //* Animates to the given value. + animateTo: function(inValue) { + this.$.animator.play({ + startValue: this.value, + endValue: inValue, + node: this.hasNode() + }); + }, + //* @protected + animatorStep: function(inSender) { + this.setValue(inSender.value); + return true; + }, + animatorComplete: function(inSender) { + if (this.tapped) { + this.tapped = false; + this.doChange({value: this.value}); + } + this.doAnimateFinish(inSender); + return true; + } +}); diff --git a/lib/onyx/source/Spinner.js b/lib/onyx/source/Spinner.js new file mode 100644 index 0000000..9f31adf --- /dev/null +++ b/lib/onyx/source/Spinner.js @@ -0,0 +1,31 @@ +/** + A control that displays a spinner animation to indicate that activity is + taking place. By default, onyx.Spinner will display a light spinner, + suitable for displaying against a dark background. To render a dark spinner + to be shown on a lighter background, add the "onyx-light" class to the + spinner: + + {kind: "onyx.Spinner", classes: "onyx-light"} + + Typically, a spinner is shown to indicate activity and hidden to indicate + that the activity has ended. The spinner animation will automatically start + when a spinner is shown. If you wish, you may control the animation directly + by calling the *start*, *stop*, and *toggle* methods. +*/ +enyo.kind({ + name: "onyx.Spinner", + classes: "onyx-spinner", + //* @public + //* Stops the spinner animation. + stop: function() { + this.setShowing(false); + }, + //* Starts the spinner animation. + start: function() { + this.setShowing(true); + }, + //* Toggles the spinner animation on or off. + toggle: function() { + this.setShowing(!this.getShowing()); + } +}); diff --git a/lib/onyx/source/TabPanels.js b/lib/onyx/source/TabPanels.js new file mode 100644 index 0000000..ae4d6da --- /dev/null +++ b/lib/onyx/source/TabPanels.js @@ -0,0 +1,128 @@ +/** +enyo.TabPanels is a subkind of enyo.Panels that +displays a set of tabs, which allow navigation between the individual panels. +Unlike enyo.Panels, by default, the user cannot drag between the panels of a +TabPanels. This behavior can be enabled by setting *draggable* to true. + +Here's an example: + + enyo.kind({ + name: "App", + kind: "TabPanels", + fit: true, + components: [ + {kind: "MyStartPanel"}, + {kind: "MyMiddlePanel"}, + {kind: "MyLastPanel"} + ] + }); + new App().write(); +*/ +enyo.kind({ + name: "enyo.TabPanels", + kind: "Panels", + //* @protected + draggable: false, + tabTools: [ + {name: "scroller", kind: "Scroller", maxHeight: "100px", strategyKind: "TranslateScrollStrategy", thumb: false, vertical: "hidden", horizontal: "auto", components: [ + {name: "tabs", kind: "onyx.RadioGroup", style: "text-align: left; white-space: nowrap", controlClasses: "onyx-tabbutton", onActivate: "tabActivate"} + ]}, + {name: "client", fit: true, kind: "Panels", classes: "enyo-tab-panels", onTransitionStart: "clientTransitionStart"} + ], + create: function() { + this.inherited(arguments); + this.$.client.getPanels = enyo.bind(this, "getClientPanels"); + this.draggableChanged(); + this.animateChanged(); + this.wrapChanged(); + }, + initComponents: function() { + this.createChrome(this.tabTools); + this.inherited(arguments); + }, + getClientPanels: function() { + return this.getPanels(); + }, + flow: function() { + this.inherited(arguments); + this.$.client.flow(); + }, + reflow: function() { + this.inherited(arguments); + this.$.client.reflow(); + }, + draggableChanged: function() { + this.$.client.setDraggable(this.draggable); + this.draggable = false; + }, + animateChanged: function() { + this.$.client.setAnimate(this.animate); + this.animate = false; + }, + wrapChanged: function() { + this.$.client.setWrap(this.wrap); + this.wrap = false; + }, + isPanel: function(inControl) { + var n = inControl.name; + return !(n == "tabs" || n == "client" || n == "scroller"); + }, + addControl: function(inControl) { + this.inherited(arguments); + if (this.isPanel(inControl)) { + var c = inControl.caption || ("Tab " + this.$.tabs.controls.length); + var t = inControl._tab = this.$.tabs.createComponent({content: c}); + if (this.hasNode()) { + t.render(); + } + } + }, + removeControl: function(inControl) { + if (this.isPanel(inControl) && inControl._tab) { + inControl._tab.destroy(); + } + this.inherited(arguments); + }, + layoutKindChanged: function() { + if (!this.layout) { + this.layout = enyo.createFromKind("FittableRowsLayout", this); + } + this.$.client.setLayoutKind(this.layoutKind); + }, + indexChanged: function() { + // FIXME: initialization order problem + if (this.$.client.layout) { + this.$.client.setIndex(this.index); + } + this.index = this.$.client.getIndex(); + }, + tabActivate: function(inSender, inEvent) { + if (this.hasNode()) { + if (inEvent.originator.active) { + var i = inEvent.originator.indexInContainer(); + if (this.getIndex() != i) { + this.setIndex(i); + } + } + } + }, + clientTransitionStart: function(inSender, inEvent) { + var i = inEvent.toIndex; + var t = this.$.tabs.getClientControls()[i]; + if (t && t.hasNode()) { + this.$.tabs.setActive(t); + var tn = t.node; + var tl = tn.offsetLeft; + var tr = tl + tn.offsetWidth; + var sb = this.$.scroller.getScrollBounds(); + if (tr < sb.left || tr > sb.left + sb.clientWidth) { + this.$.scroller.scrollToControl(t); + } + } + return true; + }, + startTransition: enyo.nop, + finishTransition: enyo.nop, + stepTransition: enyo.nop, + refresh: enyo.nop +}); \ No newline at end of file diff --git a/lib/onyx/source/TextArea.js b/lib/onyx/source/TextArea.js new file mode 100644 index 0000000..a15ac35 --- /dev/null +++ b/lib/onyx/source/TextArea.js @@ -0,0 +1,19 @@ +/** + _onyx.TextArea_ is an Onyx-styled TextArea control, derived from + enyo.TextArea. Typically, an _onyx.TextArea_ + is placed inside an onyx.InputDecorator, + which provides styling, e.g.: + + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.TextArea", onchange: "inputChange"} + ]} + + For more information, see the documentation on + [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo + Developer Guide. +*/ +enyo.kind({ + name: "onyx.TextArea", + kind: "enyo.TextArea", + classes: "onyx-textarea" +}); diff --git a/lib/onyx/source/TimePicker.js b/lib/onyx/source/TimePicker.js new file mode 100644 index 0000000..1289412 --- /dev/null +++ b/lib/onyx/source/TimePicker.js @@ -0,0 +1,210 @@ +/** + _onyx.TimePicker_ is a group of onyx.Picker + controls displaying the current time. The user may change the hour, minute, + and AM/PM values. + + By default, _TimePicker_ tries to determine the current locale and use its + rules to format the time (including AM/PM). In order to do this + successfully, the _g11n_ library must be loaded; if it is not loaded, the + control defaults to using standard U.S. time format. + */ +enyo.kind({ + name: "onyx.TimePicker", + classes: "onyx-toolbar-inline", + published: { + //* If true, control is shown as disabled, and user can't select new values + disabled: false, + /** + Current locale used for formatting. Can be set after control + creation, in which case the control will be updated to reflect the + new value. + */ + locale: "en_us", + //* If true, 24-hour time is used. This is reset when locale is changed. + is24HrMode: null, + /** + The current Date object. When a Date object is passed to _setValue_, + the control is updated to reflect the new value. _getValue_ returns + a Date object. + */ + value: null + }, + events: { + /** + Fires when one of the TimePicker's fields is selected. + + _inEvent.name_ contains the name of the TimePicker that generated + the event. + + _inEvent.value_ contains the current Date value of the control. + */ + onSelect: "" + }, + create: function() { + this.inherited(arguments); + if (enyo.g11n) { + this.locale = enyo.g11n.currentLocale().getLocale(); + } + this.initDefaults(); + }, + initDefaults: function() { + // defaults that match en_US for when g11n isn't loaded + var am = "AM", pm = "PM"; + if (this.is24HrMode == null) { + this.is24HrMode = false; + } + // Attempt to use the g11n lib (ie assume it is loaded) + if (enyo.g11n) { + this._tf = new enyo.g11n.Fmts({locale:this.locale}); + am = this._tf.getAmCaption(); + pm = this._tf.getPmCaption(); + + if (this.is24HrMode == null) { + this.is24HrMode = !this._tf.isAmPm(); + } + } + + this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : 'hma'); + + var d = this.value = this.value || new Date(); + + // create hours + var i; + if (!this.is24HrMode){ + var h = d.getHours(); + h = (h === 0) ? 12 : h; + for (i=1; i<=12; i++) { + this.$.hourPicker.createComponent({content: i, value:i, active: (i == (h>12 ? h%12 : h))}); + } + } else { + for (i=0; i<24; i++) { + this.$.hourPicker.createComponent({content: i, value:i, active: (i == d.getHours())}); + } + } + + // create minutes + for (i=0; i<=59; i++) { + this.$.minutePicker.createComponent({content: (i < 10) ? ("0"+i):i, value:i, active: i == d.getMinutes()}); + } + + // create am/pm + if (d.getHours() >= 12) { + this.$.ampmPicker.createComponents([{content: am},{content:pm, active: true}]); + } + else { + this.$.ampmPicker.createComponents([{content: am, active: true},{content:pm}]); + } + this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); + }, + setupPickers: function(ordering) { + var orderingArr = ordering.split(""); + var o,f,l; + for(f = 0, l = orderingArr.length; f < l; f++) { + o = orderingArr[f]; + switch (o){ + case 'h': this.createHour(); + break; + case 'm': this.createMinute(); + break; + case 'a': this.createAmPm(); + break; + default: break; + } + } + }, + createHour: function() { + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateHour", components: [ + {classes:"onyx-timepicker-hour", name: "hourPickerButton", disabled: this.disabled}, + {name: "hourPicker", kind: "onyx.Picker"} + ]} + ); + }, + createMinute: function() { + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateMinute", components: [ + {classes:"onyx-timepicker-minute", name: "minutePickerButton", disabled: this.disabled}, + {name: "minutePicker", kind: "onyx.Picker"} + ]} + ); + }, + createAmPm: function() { + this.createComponent( + {kind: "onyx.PickerDecorator", onSelect: "updateAmPm", components: [ + {classes:"onyx-timepicker-ampm", name: "ampmPickerButton", disabled: this.disabled}, + {name: "ampmPicker", kind: "onyx.Picker"} + ]} + ); + }, + disabledChanged: function() { + this.$.hourPickerButton.setDisabled(this.disabled); + this.$.minutePickerButton.setDisabled(this.disabled); + this.$.ampmPickerButton.setDisabled(this.disabled); + }, + localeChanged: function() { + //reset 24 hour mode when changing locales + this.is24HrMode = null; + this.refresh(); + }, + is24HrModeChanged: function() { + this.refresh(); + }, + valueChanged: function(){ + this.refresh(); + }, + updateHour: function(inSender, inEvent){ + var h = inEvent.selected.value; + if (!this.is24HrMode){ + var ampm = this.$.ampmPicker.getParent().controlAtIndex(0).content; + h = h + (h == 12 ? -12 : 0) + (this.isAm(ampm) ? 0 : 12); + } + this.value = this.calcTime(h, this.value.getMinutes()); + this.doSelect({name:this.name, value:this.value}); + return true; + }, + updateMinute: function(inSender, inEvent){ + this.value = this.calcTime(this.value.getHours(), inEvent.selected.value); + this.doSelect({name:this.name, value:this.value}); + return true; + }, + updateAmPm: function(inSender, inEvent){ + var h = this.value.getHours(); + if (!this.is24HrMode){ + h = h + (h > 11 ? (this.isAm(inEvent.content) ? -12 : 0) : (this.isAm(inEvent.content) ? 0 : 12)); + } + this.value = this.calcTime(h, this.value.getMinutes()); + this.doSelect({name:this.name, value:this.value}); + return true; + }, + calcTime: function(hour, minute){ + return new Date(this.value.getFullYear(), + this.value.getMonth(), + this.value.getDate(), + hour, minute, + this.value.getSeconds(), + this.value.getMilliseconds()); + }, + isAm: function(value){ + var am, pm, isAm; + //Workaround for pickers not having directly retrievable active item. Using it to find whether + //picker is on AM or PM (& have to check localized spelling as well) + try { + am = this._tf.getAmCaption(); + pm = this._tf.getPmCaption(); + } catch (err) { + am = "AM"; + pm = "PM"; + } + + if (value == am){ + return true; + } else { + return false; + } + }, + refresh: function(){ + this.destroyClientControls(); + this.initDefaults(); + this.render(); + } +}); diff --git a/lib/onyx/source/ToggleButton.js b/lib/onyx/source/ToggleButton.js new file mode 100644 index 0000000..8fffbcb --- /dev/null +++ b/lib/onyx/source/ToggleButton.js @@ -0,0 +1,118 @@ +/** + _onyx.ToggleButton_ is a control that looks like a switch with labels for + two states. Each time a ToggleButton is tapped, it switches its value and + fires an _onChange_ event. + + To get the value of the button, call _getValue_. + + For more information, see the documentation on + [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer + Guide. +*/ +enyo.kind({ + name: "onyx.ToggleButton", + classes: "onyx-toggle-button", + published: { + //* Used when the ToggleButton is part of a enyo.Group, true + //* to indicate that this is the active button of the group, false otherwise. + active: false, + //* Boolean indicating whether toggle button is currently in the "on" + //* state + value: false, + //* Label for toggle button's "on" state + onContent: "On", + //* Label for toggle button's "off" state + offContent: "Off", + //* If true, toggle button cannot be tapped and thus will not generate + //* any events + disabled: false + }, + events: { + /** + Fires when the user changes the value of the toggle button, but not + when the value is changed programmatically. + + _inEvent.value_ contains the value of the toggle button. + */ + onChange: "" + }, + //* @protected + handlers: { + ondragstart: "dragstart", + ondrag: "drag", + ondragfinish: "dragfinish" + }, + components: [ + {name: "contentOn", classes: "onyx-toggle-content on"}, + {name: "contentOff", classes: "onyx-toggle-content off"}, + {classes: "onyx-toggle-button-knob"} + ], + create: function() { + this.inherited(arguments); + this.value = Boolean(this.value || this.active); + this.onContentChanged(); + this.offContentChanged(); + this.disabledChanged(); + }, + rendered: function() { + this.inherited(arguments); + this.updateVisualState(); + }, + updateVisualState: function() { + this.addRemoveClass("off", !this.value); + this.$.contentOn.setShowing(this.value); + this.$.contentOff.setShowing(!this.value); + this.setActive(this.value); + }, + valueChanged: function() { + this.updateVisualState(); + this.doChange({value: this.value}); + }, + activeChanged: function() { + this.setValue(this.active); + this.bubble("onActivate"); + }, + onContentChanged: function() { + this.$.contentOn.setContent(this.onContent || ""); + this.$.contentOn.addRemoveClass("empty", !this.onContent); + }, + offContentChanged: function() { + this.$.contentOff.setContent(this.offContent || ""); + this.$.contentOff.addRemoveClass("empty", !this.onContent); + }, + disabledChanged: function() { + this.addRemoveClass("disabled", this.disabled); + }, + updateValue: function(inValue) { + if (!this.disabled) { + this.setValue(inValue); + } + }, + tap: function() { + this.updateValue(!this.value); + }, + dragstart: function(inSender, inEvent) { + if (inEvent.horizontal) { + inEvent.preventDefault(); + this.dragging = true; + this.dragged = false; + return true; + } + }, + drag: function(inSender, inEvent) { + if (this.dragging) { + var d = inEvent.dx; + if (Math.abs(d) > 10) { + this.updateValue(d > 0); + this.dragged = true; + } + return true; + } + }, + dragfinish: function(inSender, inEvent) { + this.dragging = false; + if (this.dragged) { + inEvent.preventTap(); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/source/ToggleIconButton.js b/lib/onyx/source/ToggleIconButton.js new file mode 100644 index 0000000..df97438 --- /dev/null +++ b/lib/onyx/source/ToggleIconButton.js @@ -0,0 +1,58 @@ +/** + _onyx.ToggleIconButton_ is an icon that acts like a toggle switch. The icon + image is specified by setting the _src_ property to a URL. + + {kind: "onyx.ToggleIconButton", src: "images/search.png", ontap: "buttonTap"} + + The image associated with the _src_ property is assumed to be a 32x64-pixel + strip, with the top half showing the button's normal state and the bottom + half showing its state when hovered-over or active. +*/ + +enyo.kind({ + name: "onyx.ToggleIconButton", + kind: "onyx.Icon", + published: { + /** + Used when the ToggleIconButton is part of an enyo.Group; set to true + to indicate that this is the active button in the group. + */ + active: false, + //* Boolean indicating whether the button is currently in the "on" state + value: false + }, + events: { + /** + Fires when the user changes the value of the toggle button, but not + when the value is changed programmatically. + */ + onChange: "" + }, + classes: "onyx-icon-button onyx-icon-toggle", + //* @protected + activeChanged: function() { + this.addRemoveClass("active", this.value); + this.bubble("onActivate"); + }, + updateValue: function(inValue) { + if (!this.disabled) { + this.setValue(inValue); + this.doChange({value: this.value}); + } + }, + tap: function() { + this.updateValue(!this.value); + }, + valueChanged: function() { + this.setActive(this.value); + }, + create: function() { + this.inherited(arguments); + this.value = Boolean(this.value || this.active); + }, + rendered: function() { + this.inherited(arguments); + this.valueChanged(); + this.removeClass('onyx-icon'); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/Toolbar.js b/lib/onyx/source/Toolbar.js new file mode 100644 index 0000000..09c06bb --- /dev/null +++ b/lib/onyx/source/Toolbar.js @@ -0,0 +1,31 @@ +/** + _onyx.Toolbar_ is a horizontal bar containing controls used to perform + common UI actions. + + A Toolbar customizes the styling of the controls it hosts, including + buttons, icons, and inputs. + + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "Favorites"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Enter a search term..."} + ]}, + {kind: "onyx.IconButton", src: "go.png"} + ]} + + For more information, see the documentation on + Toolbars in the + Enyo Developer Guide. +*/ +enyo.kind({ + name: "onyx.Toolbar", + classes: "onyx onyx-toolbar onyx-toolbar-inline", + create: function(){ + this.inherited(arguments); + + //workaround for android 4.0.3 rendering glitch (ENYO-674) + if (this.hasClass('onyx-menu-toolbar') && (enyo.platform.android >= 4)){ + this.applyStyle("position", "static"); + } + } +}); \ No newline at end of file diff --git a/lib/onyx/source/Tooltip.js b/lib/onyx/source/Tooltip.js new file mode 100644 index 0000000..6cf4b9a --- /dev/null +++ b/lib/onyx/source/Tooltip.js @@ -0,0 +1,86 @@ +/** + _onyx.Tooltip_ is a kind of onyx.Popup that works + with an onyx.TooltipDecorator. It + automatically displays a tooltip when the user hovers over the decorator. + The tooltip is positioned around the decorator where there is available + window space. + + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.Button", content: "Tooltip"}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} + ]} + + You may manually display the tooltip by calling its _show_ method. +*/ +enyo.kind({ + name: "onyx.Tooltip", + kind: "onyx.Popup", + classes: "onyx-tooltip below left-arrow", + //* If true, tooltip is automatically dismissed when user stops hovering + //* over the decorator + autoDismiss: false, + //* Hovering over the decorator for this length of time (in milliseconds) + //* causes the tooltip to appear. + showDelay: 500, + //* Default margin-left value + defaultLeft: -6, + //* @protected + handlers: { + onRequestShowTooltip: "requestShow", + onRequestHideTooltip: "requestHide" + }, + requestShow: function() { + this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay); + return true; + }, + cancelShow: function() { + clearTimeout(this.showJob); + }, + requestHide: function() { + this.cancelShow(); + return this.inherited(arguments); + }, + showingChanged: function() { + this.cancelShow(); + this.adjustPosition(true); + this.inherited(arguments); + }, + applyPosition: function(inRect) { + var s = ""; + for (var n in inRect) { + s += (n + ":" + inRect[n] + (isNaN(inRect[n]) ? "; " : "px; ")); + } + this.addStyles(s); + }, + adjustPosition: function(belowActivator) { + if (this.showing && this.hasNode()) { + var b = this.node.getBoundingClientRect(); + + //when the tooltip bottom goes below the window height move it above the decorator + if (b.top + b.height > window.innerHeight) { + this.addRemoveClass("below", false); + this.addRemoveClass("above", true); + } else { + this.addRemoveClass("above", false); + this.addRemoveClass("below", true); + } + + //when the tooltip's right edge is out of the window, align its right edge with the decorator left edge (approx) + if (b.left + b.width > window.innerWidth){ + this.applyPosition({'margin-left': -b.width, bottom: "auto"}); + //use the right-arrow + this.addRemoveClass("left-arrow", false); + this.addRemoveClass("right-arrow", true); + } + } + }, + resizeHandler: function() { + //reset the tooltip to align its left edge with the decorator + this.applyPosition({'margin-left': this.defaultLeft, bottom: "auto"}); + this.addRemoveClass("left-arrow", true); + this.addRemoveClass("right-arrow", false); + + this.adjustPosition(true); + this.inherited(arguments); + } +}); diff --git a/lib/onyx/source/TooltipDecorator.js b/lib/onyx/source/TooltipDecorator.js new file mode 100644 index 0000000..0bfe9a8 --- /dev/null +++ b/lib/onyx/source/TooltipDecorator.js @@ -0,0 +1,45 @@ +/** + A control that activates an onyx.Tooltip. It + surrounds a control such as a button and displays the tooltip when the + control generates an _onEnter_ event: + + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.Button", content: "Tooltip"}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} + ]} + + Here's an example with an onyx.Input control and a + decorator around the input: + + {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Just an input..."} + ]}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} + ]} +*/ +enyo.kind({ + name: "onyx.TooltipDecorator", + defaultKind: "onyx.Button", + //* @protected + classes: "onyx-popup-decorator", + handlers: { + onenter: "enter", + onleave: "leave" + }, + enter: function() { + this.requestShowTooltip(); + }, + leave: function() { + this.requestHideTooltip(); + }, + tap: function() { + this.requestHideTooltip(); + }, + requestShowTooltip: function() { + this.waterfallDown("onRequestShowTooltip"); + }, + requestHideTooltip: function() { + this.waterfallDown("onRequestHideTooltip"); + } +}); \ No newline at end of file diff --git a/lib/onyx/source/design.js b/lib/onyx/source/design.js new file mode 100644 index 0000000..17e4c7d --- /dev/null +++ b/lib/onyx/source/design.js @@ -0,0 +1,168 @@ +//* @protected +// Design description of the Onyx controls for use in the Ares designer tool. +Palette.model.push( + {name: "onyx", items: [ + {name: "onyx.Button", description: "A Pushbutton", + inline: {content: "onyx.Button", kind: "onyx.Button"}, + config: {content: "$name", isContainer: true, kind: "onyx.Button"} + }, + {name: "onyx.Checkbox", description: "A checkbox", + inline: {kind: "onyx.Checkbox"}, + config: {kind: "onyx.Checkbox"} + }, + {name: "onyx.DatePicker", description: "A control for choosing a date", + inline: {kind: "onyx.DatePicker"}, + config: {kind: "onyx.DatePicker"} + }, + {name: "onyx.Drawer", description: "A drawer that opens and closes", + inline: {kind: "onyx.Drawer"}, + config: {kind: "onyx.Drawer"} + }, + {name: "onyx.Groupbox", description: "A container for a group of controls", + inline: {kind: "onyx.Groupbox", components: [ + {content: "Header", kind: "onyx.GroupboxHeader"}, + {content: "Item", style: "padding: 10px;"} + ]}, + config: {kind: "onyx.Groupbox", isContainer: true, components: [ + {content: "Header", kind: "onyx.GroupboxHeader", isContainer: true}, + {content: "Item", style: "padding: 10px;"} + ]} + }, + {name: "onyx.GroupboxHeader", description: "A header for the Groupbox", + inline: {content: "Header", kind: "onyx.GroupboxHeader"}, + config: {content: "$name", kind: "onyx.GroupboxHeader", isContainer: true} + }, + {name: "onyx.Icon", description: "An Icon", + inline: {kind: "onyx.Icon"}, + config: {kind: "onyx.Icon"} + }, + {name: "onyx.IconButton", description: "An IconButton", + inline: {kind: "onyx.IconButton"}, + config: {kind: "onyx.IconButton"} + }, + {name: "onyx.InputDecorator", description: "Style an Input", + inline: {kind: "onyx.InputDecorator", components: [ + {kind: "Input", placeholder: "Enter text here"} + ]}, + config: {kind: "onyx.InputDecorator", components: [ + {kind: "Input", placeholder: "Enter text here"} + ]} + }, + {name: "onyx.Input", description: "Text input control", + inline: {value: "onyx.Input", kind: "onyx.Input"}, + config: {kind: "onyx.Input"} + }, + {name: "onyx.Item", description: "Stackable item, for lists and menus", + inline: {value: "onyx.Item", kind: "onyx.Item"}, + config: {content: "$name", kind: "onyx.Item"} + }, + {name: "onyx.MenuDecorator", description: "A Menu and activating control", + inline: {}, + config: {kind: "onyx.MenuDecorator", components: [ + {content: "Show menu"}, + {kind: "onyx.Menu", components: [ + {content: "1"}, + {content: "2"}, + {classes: "onyx-menu-divider"}, + {content: "Label", classes: "onyx-menu-label"}, + {content: "3"} + ]} + ]} + }, + {name: "onyx.PickerDecorator", description: "A Picker and activating control", + inline: {}, + config: {kind: "onyx.PickerDecorator", components: [ + {content: "Pick1"}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton + {kind: "onyx.Picker", components: [ + {content: "Pick1", active: true}, + {content: "Pick2"}, + {content: "Pick3"}, + {content: "Pick4"} + ]} + ]} + }, + {name: "onyx.ProgressBar", description: "A progress bar", + inline: {}, + config: {kind: "onyx.ProgressBar"} + }, + {name: "onyx.ProgressButton", description: "A progress button", + inline: {}, + config: {kind: "onyx.ProgressButton"} + }, + {name: "onyx.RadioGroup", description: "Only one control in a group can be 'active' at a time", + inline: {kind: "onyx.RadioGroup", components: [ + {content: "A"}, + {content: "B"}, + {content: "C"} + ]}, + config: {kind: "onyx.RadioGroup", isContainer: true, components: [ + {content: "RadioButton"} + ]} + }, + {name: "onyx.RadioButton", description: "An on-off button, for use with RadioGroup", + inline: {content: "RadioButton", kind: "onyx.RadioButton"}, + config: {content: "$name", kind: "onyx.RadioButton"} + }, + {name: "onyx.RangeSlider", description: "A Slider with two knobs", + inline: {value: "onyx.RangeSlider", kind: "onyx.RangeSlider"}, + config: {kind: "onyx.RangeSlider"} + }, + {name: "onyx.RichText", description: "A Rich text input", + inline: {value: "onyx.RichText", kind: "onyx.RichText"}, + config: {kind: "onyx.RichText", style: "height: 100px"} + }, + {name: "onyx.Slider", description: "A Slider", + inline: {value: "onyx.Slider", kind: "onyx.Slider"}, + config: {kind: "onyx.Slider"} + }, + {name: "onyx.Spinner", description: "A Spinner", + inline: {kind: "onyx.Spinner"}, + config: {kind: "onyx.Spinner", classes: "onyx-light"} + }, + {name: "onyx.TextArea", description: "A multi-line text input", + inline: {kind: "onyx.TextArea"}, + config: {kind: "onyx.TextArea"} + }, + {name: "onyx.TimePicker", description: "A Picker for time", + inline: {kind: "onyx.TimePicker"}, + config: {kind: "onyx.TimePicker"} + }, + {name: "onyx.ToggleButton", description: "A pushbutton that toggles between active and inactive states", + inline: {kind: "onyx.ToggleButton"}, + config: {kind: "onyx.ToggleButton"} + }, + {name: "onyx.ToggleIconButton", description: "A ToggleButton that toggles between active and inactive images", + inline: {kind: "onyx.ToggleIconButton"}, + config: {kind: "onyx.ToggleIconButton"} + }, + {name: "onyx.Toolbar", description: "A toolbar", + inline: {kind: "onyx.Toolbar"}, + config: {isContainer: true, kind: "onyx.Toolbar"} + }, + {name: "onyx.MoreToolbar", description: "A toolbar which adapts to screen width ", + inline: {kind: "onyx.Toolbar"}, + config: {isContainer: true, kind: "onyx.MoreToolbar", components: [ + {content: "MoreToolbar"}, + {kind: "onyx.Item", content: "Resize Me!"}, + {kind: "onyx.Button", content: "this"}, + {kind: "onyx.Button", content: "toolbar"}, + {kind: "onyx.Button", content: "has"}, + {kind: "onyx.Button", content: "many"}, + {kind: "onyx.Button", content: "items"}, + {kind: "onyx.Button", content: "in"}, + {kind: "onyx.Button", content: "it"} + ]} + }, + {name: "onyx.Grabber", description: "Graphical 'handle' for dragging", + inline: {kind: "onyx.Grabber", style: "background-color: #333; padding: 4px 12px;"}, + config: {kind: "onyx.Grabber"} + }, + {name: "onyx.TooltipDecorator", description: "Combines a conrol (typically a button) and a tooltip describing it", + inline: {kind: "onyx.Tooltip"}, + config: {kind: "onyx.TooltipDecorator", components: [ + {kind: "onyx.Button", content: "Hover for tooltip"}, + {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} + ]} + } + ]} +); diff --git a/lib/onyx/source/package.js b/lib/onyx/source/package.js new file mode 100644 index 0000000..a5f763e --- /dev/null +++ b/lib/onyx/source/package.js @@ -0,0 +1,42 @@ +enyo.depends( + "Icon.js", + "Button.js", + "IconButton.js", + "Checkbox.js", + "Drawer.js", + "Grabber.js", + "Groupbox.js", + "Input.js", + "Popup.js", + "TextArea.js", + "RichText.js", + "InputDecorator.js", + "Tooltip.js", + "TooltipDecorator.js", + "MenuDecorator.js", + "Menu.js", + "MenuItem.js", + "PickerDecorator.js", + "PickerButton.js", + "Picker.js", + "FlyweightPicker.js", + "DatePicker.js", + "TimePicker.js", + "RadioButton.js", + "RadioGroup.js", + "ToggleButton.js", + "ToggleIconButton.js", + "Toolbar.js", + "Tooltip.js", + "TooltipDecorator.js", + "ProgressBar.js", + "ProgressButton.js", + "Scrim.js", + "Slider.js", + "RangeSlider.js", + "Item.js", + "Spinner.js", + "MoreToolbar.js", + "IntegerPicker.js", + "ContextualPopup.js" +); \ No newline at end of file diff --git a/lib/onyx/source/wip-package.js b/lib/onyx/source/wip-package.js new file mode 100644 index 0000000..a00be44 --- /dev/null +++ b/lib/onyx/source/wip-package.js @@ -0,0 +1,3 @@ +enyo.depends( + "TabPanels.js" +); \ No newline at end of file diff --git a/package.js b/package.js index 2a0b582..ac5ed78 100644 --- a/package.js +++ b/package.js @@ -1,6 +1,5 @@ -enyo.depends( - "$lib/layout", - "$lib/onyx", - "source/App.css", - "source/App.js" -); +/* + == DO NOT EDIT THIS FILE! == + This is necessary to keep paths correct for the minification process +*/ +enyo.depends("source"); diff --git a/source/Scheduler.css b/source/Scheduler.css new file mode 100644 index 0000000..ca84d09 --- /dev/null +++ b/source/Scheduler.css @@ -0,0 +1,94 @@ +/* + Put anything you reference with "url()" in ../assets/ + This way, you can minify your application, and just remove the "source" folder for production +*/ + +#upper_toolbar{ + text-align: center; +} + +#bottom_toolbar{ + height: 70px; +} + + +.nice-padding { + padding: 3px; +} + +.button_image{ + height: 40px; + width: 40px; +} + +.onyx-sample-tools > * { + margin: 3px; +} + +.button{ + height: 50px; + width: 50px; + margin: 0px 10px 0px 10px; + border: 0 0 0 0; + padding: 0 0 0 0; +} + +.onyx-sample { + padding: 10px; +} +.onyx-sample-tools { + padding-bottom:10px; +} + +.onyx-sample-divider { + color: #F49200; + text-transform: uppercase; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; + font-weight: bold; + margin-bottom: 8px; +} +.onyx-sample-result-box { + width:100%; +} +.onyx-sample-result { + padding:8px; +} +.onyx-sample-spaced-button { + margin:3px; +} +.onyx-sample-animate-label { + vertical-align:middle; + padding-left:5px; + margin-right: 15px; +} +.onyx-sample-label { + color: #1879CD; + font-size: 18px; + text-transform: uppercase; +} +.onyx-sample-popup { + font-size: 30px; + text-align: center; +} +.onyx-contextualpopup-button-container{ + padding:10px; +} + +.onyx-sample-tools.group{ + position: relative; + left: 50%; + margin-left: -105px; +} + +.Input{ + text-align: center; +} + +.onyx-sample-result{ + text-align: center; +} + +.result_header{ + text-align: center; +} \ No newline at end of file diff --git a/source/Scheduler.js b/source/Scheduler.js new file mode 100644 index 0000000..8986875 --- /dev/null +++ b/source/Scheduler.js @@ -0,0 +1,55 @@ +enyo.kind({ + name: "Scheduler", + kind: "FittableRows", + fit: true, + published:{ + init : 0 + }, + components:[ + //toobar showing the tapped function + {kind: "onyx.Toolbar", name: "scheduler_toolbar", id: "upper_toolbar", content: "To do Lists"}, + {kind: "enyo.Scroller", fit: true, components: [ + {name: "main", classes: "nice-padding", allowHtml: true} + ]}, + // bottom toolbar and buttons + {kind: "onyx.Toolbar", id: "bottom_toolbar", components: [ + //buttons + {kind: "Group", onActivate:"buttonActivated", classes: "onyx-sample-tools group", defaultKind: "onyx.Button", highlander: true, + components: [ + {components:[{kind:"Image", classes:"button_image" ,src: "assets/check.png"}] , id: "To do Lists", active: true, classes: "button"}, + {components:[{kind:"Image", classes:"button_image" ,src: "assets/week.png"}] , id: "Weekly Schedule", classes: "button"}, + {components:[{kind:"Image", classes:"button_image" ,src: "assets/month.png"}] , id: "Calendar", classes: "button"}]}, + ]}, + ], + + buttonActivated: function(inSender, inEvent) { + // render only when it is started + if (this.init == 0){ + this.$.main.createComponent({kind:"To_do", name: "To_do"}); + this.$.main.createComponent({kind:"weekly", name: "weekly"}); + this.$.main.createComponent({kind: "calendar", name:"calendar"}); + this.$.main.render(); + this.init++; + } + // when each button is tapped show the tapped component and hide the others + if (inEvent.originator.getActive()) { + this.$.scheduler_toolbar.setContent(inEvent.originator.getId()); + if(inEvent.originator.getId() == "To do Lists"){ + this.$.main.$.weekly.hide(); + this.$.main.$.calendar.hide(); + this.$.main.$.To_do.show(); + } + else if(inEvent.originator.getId() == "Weekly Schedule"){ + this.$.main.$.To_do.hide(); + this.$.main.$.calendar.hide(); + this.$.main.$.weekly.show(); + } + else{ + this.$.main.$.To_do.hide(); + this.$.main.$.weekly.hide(); + this.$.main.$.calendar.show(); + } + } + } + +}); diff --git a/source/Theme.less b/source/Theme.less new file mode 100644 index 0000000..b9b13c8 --- /dev/null +++ b/source/Theme.less @@ -0,0 +1,26 @@ +/* + You can modify the Onyx theme by adding variable and rule overrides to this + file. To enable theming, follow these steps: + + 1. In debug.html, uncomment the line referencing "less-.min.js". + 2. In package.js, change "$lib/onyx" to "$lib/onyx/source". + 3. Also in package.js, add "Theme.less" (this file). + 4. Add variable and rule overrides below. + + See [https://github.com/enyojs/enyo/wiki/UI-Theming] for more information. +*/ + + +/* Onyx default variable definitions: */ +@import "../lib/onyx/css/onyx-variables.less"; + +/* Place your Onyx variable overrides here -------------------- */ + +/* ------------------------------------- end variable overrides */ + +/* Onyx rule definitions: */ +@import "../lib/onyx/css/onyx-rules.less"; + +/* Place your Onyx rule overrides here ------------------------ */ + +/* ----------------------------------------- end rule overrides */ diff --git a/source/function/calendar.css b/source/function/calendar.css new file mode 100644 index 0000000..a44fbaa --- /dev/null +++ b/source/function/calendar.css @@ -0,0 +1,73 @@ +.calendar { + padding: 0 20px; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; +} +.calendar table { + width: 100%; + height: 90%; + border-collapse: collapse; +} +.calendar .header td { + padding: 5px 2px; + width: 14%; + height: 16px; + font-weight: bold; + text-transform: uppercase; + text-align: center; +} +.calendar .header td:first-of-type { + color: red; +} + +.calendar .header td:last-of-type { + color: blue; +} + +.calendar td { + padding: 2px; + vertical-align: top; + border: 1px solid #999; + background-color: #FFF; +} +.calendar td.current { + background-color: #226B9A; + color: #FFF; + font-weight: bold; +} +.calendar .section { + padding-top: 20px; + font-size: 20px; + display: block; + color: #000000; + text-transform: uppercase; + font-weight: bold; + margin-bottom: 8px; + text-align: center; +} +.calendar .results { + margin: 20px 0; + padding: 20px; + min-height: 24px; + border-radius: 10px; + color: #FFF; + background-color: #555; +} + +.prev_button{ + float: left; +} + +.next_button{ + float: right; +} + +.contentSection{ + display: inline; +} + +.Typing{ + width: 115px; + height: 25px; + text-align: center; +} \ No newline at end of file diff --git a/source/function/calendar.js b/source/function/calendar.js new file mode 100644 index 0000000..3c5d33d --- /dev/null +++ b/source/function/calendar.js @@ -0,0 +1,416 @@ +enyo.kind({ + name: "calendar", + classes: "calendar enyo-fit", + published:{ + "setYear":"", + "setMonth":"" + }, + components: [ + {name: "month", classes: "section", allowHtml: true, components:[ + {kind: "onyx.IconButton", src: "assets/left_arrow.png", ontap:"leftTapped", classes:"prev_button"}, + {name: "innerMonth", classes: "contentSection", ontap:"calendarTapped", popup:"popupInput"}, + {name: "popupInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components:[ + {classes:"inputContainer", components:[ + {name: "yearInput", kind: "onyx.Input", placeholder: "Type Year here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, + {content: "년", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, + {name: "monthInput", kind: "onyx.Input", placeholder: "Type Month here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, + {content: "월", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, + ]}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, + {kind: "onyx.Button", content: "Apply", ontap: "applyYearMonth", classes: "popupButton", popup: "showMessage"}, + {name: "showMessage", kind: "onyx.Popup",onkeypress:"closeMessagePopup2", centered: true, modal: true, floating: true, components:[ + {name:"popupContents", content:"", allowHtml: true}, + {tag: "br"}, + {kind:"onyx.Button", content: "Close", ontap: "closeMessagePopup", style:"position:relative; left: 50%; margin-left: -39.5px"} + ]} + ]}, + {kind: "onyx.IconButton", src: "assets/right_arrow.png", ontap:"rightTapped", classes:"next_button"} + ]}, + {name:"monthTable", kind: "enyo.Table", components: [ + {classes: "header", components: [ + {content: "Sun"}, + {content: "Mon"}, + {content: "Tue"}, + {content: "Wed"}, + {content: "Thu"}, + {content: "Fri"}, + {content: "Sat"} + ]} + ]} + ], + create: function() { + if(!localStorage.count_c){ + localStorage.setItem('count_c', '0'); + } + this.inherited(arguments); + + var currentRow, + dateObj = new Date(); + + // calculate current date + var currentDate = dateObj.getDate(); + + // calculate date of first day of the month + dateObj.setDate(1); + var offset = dateObj.getDay(); + + // calculate date of last day of the month + this.setYear = dateObj.getFullYear(); + this.setMonth = dateObj.getMonth(); + var lastDate = this.getDaysInMonth(dateObj.getMonth(), dateObj.getFullYear()); + + // this calculation can probably be simplified, but allows for padding blank spaces in + // the calendar to display a "full" table + for (var i=0; i=lastDate+offset) { + currentRow.createComponent({}); + } else { + var cellDay = new functionCell(); + cellDay.number = (i-offset+1); + cellDay.year = this.setYear; + cellDay.month = this.setMonth; + if ((i-offset+1) === currentDate) { + cellDay.active = true; + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + } + + // set month display + this.$.innerMonth.setContent(dateObj.getFullYear() + "년 " + (dateObj.getMonth()+1) +"월"); + }, + // adapted from http://stackoverflow.com/questions/1810984/number-of-days-in-any-month + getDaysInMonth: function(m, y) { + return (/8|3|5|10/).test(m)?30:m==1?((y%4===0)&&y%100)||(y%400===0)?29:28:31; + }, + + leftTapped: function(inSender, inEvent){ + this.$.monthTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + if(this.setMonth > 0){ + this.setMonth -= 1; + } + else{ + this.setMonth = 11; + this.setYear -= 1; + } + var dateObj2 = new Date(this.setYear, this.setMonth, 1); + var currentDate = dateObj.getDate(); + var offset = dateObj2.getDay(); + var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); + // this calculation can probably be simplified, but allows for padding blank spaces in + // the calendar to display a "full" table + for (var i=0; i=lastDate+offset) { + currentRow.createComponent({}); + } else { + var cellDay = new functionCell(); + cellDay.number = (i-offset+1); + cellDay.year = this.setYear; + cellDay.month = this.setMonth; + if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { + cellDay.active = true; + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + } + + // set month display + this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); + this.$.monthTable.render(); + }, + + rightTapped: function(inSender,inEvent){ + this.$.monthTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + if(this.setMonth < 11){ + this.setMonth += 1; + } + else{ + this.setMonth = 0; + this.setYear += 1; + } + var dateObj2 = new Date(this.setYear, this.setMonth, 1); + var currentDate = dateObj.getDate(); + var offset = dateObj2.getDay(); + var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); + // this calculation can probably be simplified, but allows for padding blank spaces in + // the calendar to display a "full" table + for (var i=0; i=lastDate+offset) { + currentRow.createComponent({}); + } else { + var cellDay = new functionCell(); + cellDay.number = (i-offset+1); + cellDay.year = this.setYear; + cellDay.month = this.setMonth; + if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { + cellDay.active = true; + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + } + + // set month display + this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); + this.$.monthTable.render(); + }, + + calendarTapped: function(inSender, inEvent){ + this.$.popupInput.show(); + }, + + closePopup: function(inSender, inEvent){ + this.$.popupInput.hide(); + }, + + popupShown: function() { + this.$.yearInput.focus(); + }, + + enterDetected: function(inSender, inEvent){ + if(inEvent.keyCode == 13){ + this.applyYearMonth(); + } + }, + + applyYearMonth: function(inSender, inEvent){ + var yearInputValue = parseFloat(this.$.yearInput.getValue()); + var monthInputValue = parseFloat(this.$.monthInput.getValue() - 1); + if(this.$.yearInput.getValue() == ""){ + this.$.popupContents.setContent("please input Year value!"); + this.$.showMessage.show(); + return; + } + if(this.$.monthInput.getValue() == ""){ + this.$.popupContents.setContent("please input Month value!"); + this.$.showMessage.show(); + return; + } + if(this.isInt(yearInputValue) == false){ + this.$.popupContents.setContent("Invalid Year value!
    please input integer value"); + this.$.showMessage.show(); + return; + } + else if(yearInputValue < 1000 || yearInputValue > 3000){ + this.$.popupContents.setContent("Invalid Year value!
    please input value between 1000 ~ 3000"); + this.$.showMessage.show(); + return; + } + this.setYear = yearInputValue; + if(this.isInt(monthInputValue) == false){ + this.$.popupContents.setContent("Invalid Month value!
    please input integer value"); + this.$.showMessage.show(); + return; + } + else if(monthInputValue < 0 || monthInputValue > 11){ + this.$.popupContents.setContent("Invalid Month value!
    please input value between 1 ~ 12"); + this.$.showMessage.show(); + return; + } + this.setMonth = monthInputValue; + this.$.popupInput.hide(); + this.$.monthTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + this.$.yearInput.clear(); + this.$.monthInput.clear(); + + var dateObj2 = new Date(this.setYear, this.setMonth, 1); + var currentDate = dateObj.getDate(); + var offset = dateObj2.getDay(); + var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); + // this calculation can probably be simplified, but allows for padding blank spaces in + // the calendar to display a "full" table + for (var i=0; i=lastDate+offset) { + currentRow.createComponent({}); + } else { + var cellDay = new functionCell(); + cellDay.number = (i-offset+1); + cellDay.year = this.setYear; + cellDay.month = this.setMonth; + if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { + cellDay.active = true; + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + } + + // set month display + this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); + this.$.monthTable.render(); + }, + + closeMessagePopup: function(inSender, inEvent){ + this.$.showMessage.hide(); + }, + + closeMessagePopup2: function(inSender,inEvent){ + if(inEvent.keyCode == 13){ + this.closeMessagePopup(); + } + }, + + isInt: function(value){ + return typeof(value) === 'number' && value % 1 == 0; + }, + + ontapTest: function(inSender, inEvent){ + alert('this is a ' + inSender.getContent()); + + }, +}); + +enyo.kind({ + name:"functionCell", + kind:"enyo.TableCell", + components:[ + {name: "cellContent", popup:"scheduleInput", popup:"scheduleShow", content:""}, + {name:"scheduleInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "", components:[ + {content: "제목", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, + {name: "subjectInput", kind: "onyx.Input", placeholder: "Type subject here", classes:"Typing", style: "margin: 10px", onkeypress:""}, + {tag:"br"}, + {content: "시간", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, + {name: "timeInput", kind: "onyx.Input", placeholder: "Type Time(00:00) here", classes:"Typing", style: "margin: 10px", onkeypress:""}, + {tag:"br"}, + {content: "장소", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, + {name: "placeInput", kind: "onyx.Input", placeholder: "Type Place here", classes:"Typing", style: "margin: 10px", onkeypress:""}, + {tag:"br"}, + {tag:"br"}, + {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, + {kind: "onyx.Button", content: "Apply", ontap: "applySchedule", classes: "popupButton"} + ]}, + {name:"scheduleShow", kind:"onyx.Popup", onHide:"ScheduleListHide", modal: true, floating: true, components:[ + {kind: "onyx.Groupbox", components: [ + {name:"scheduleList", kind: "onyx.GroupboxHeader", content: "Schedule List"} + ]} + ]}, + {name: "scheduleImage", kind:"enyo.Image", src:"assets/dot.png", active: false, style:"position: relative; left: 95%; height: 10px; width: 10px;"}, + {name: "schedule", components:[ + {name:"subject", content:""}, + {name:"time", content:""}, + {name:"place", content:""} + ]} + ], + published:{ + active: false, + isSchedule: false, + number: "", + year: "", + month: "", + }, + handlers:{ + ontap:"cellTap", + onleave: "cellDeactive" + }, + create: function(){ + this.inherited(arguments); + this.$.cellContent.setContent(this.number); + + for(var i = 1 ; i < parseInt(localStorage.count_c)+1 ; i++){ + if((localStorage.getItem(i.toString()+'c')) != null){ + var Obj = {}; + Obj = JSON.parse(localStorage.getItem(i.toString()+'c')); + if(Obj.year == this.year && Obj.month == this.month && Obj.date == this.number){ + this.restoreSchedule(Obj.subject, Obj.time, Obj.place); + } + } + } + + this.$.schedule.hide(); + if(this.isSchedule == false){ + this.$.scheduleImage.hide(); + } + }, + restoreSchedule: function(subject, time, place){ + var newSchedule = new scheduleThing(); + newSchedule.setContent(time + "에 " + place + "에서 " + subject +"이(가) 있습니다."); + this.$.scheduleList.createComponent(newSchedule); + this.$.scheduleList.render(); + this.isSchedule = true; + this.$.scheduleImage.show(); + }, + cellTap: function(inSender, inEvent){ + if(this.active == false){ + this.active = true; + this.applyStyle("background-color","yellow"); + if(this.isSchedule == true){ + this.$.scheduleShow.showAtEvent(inEvent); + } + } + else if(this.active == true){ + this.$.scheduleInput.show(); + } + }, + cellDeactive: function(inSender, inEvent){ + if(this.active == true){ + this.active = false; + this.applyStyle("background-color", "white"); + if(this.getClassAttribute() == "current"){ + this.applyStyle("background-color", "#226B9A"); + } + } + }, + closePopup: function(inSender, inEvent){ + this.$.scheduleInput.hide(); + }, + + applySchedule: function(inSender, inEvent){ + var subject = this.$.subjectInput.getValue(); + var time = this.$.timeInput.getValue(); + var place = this.$.placeInput.getValue(); + this.$.subjectInput.clear(); + this.$.timeInput.clear(); + this.$.placeInput.clear(); + + var newSchedule = new scheduleThing(); + newSchedule.setContent(time + "에 " + place + "에서 " + subject +"이(가) 있습니다."); + var count_c = parseInt(localStorage.count_c); + count_c++; + localStorage.setItem('count_c', count_c); + var Obj_c = []; + Obj_c[count_c] = {year: this.year, month: this.month, date: this.number, subject: subject, time: time, place: place }; + localStorage.setItem(count_c.toString() + 'c', JSON.stringify(Obj_c[count_c])); + this.$.scheduleList.createComponent(newSchedule); + this.$.scheduleList.render(); + this.isSchedule = true; + this.$.scheduleImage.show(); + this.$.scheduleInput.hide(); + }, + + ScheduleListHide: function(inSender, inEvent){ + if(this.active == false){ + this.active = true; + this.applyStyle("background-color","yellow"); + } + } +}); + +enyo.kind({ + name: "scheduleThing", + content: "", + handlers:{ + ontap: "editSchedule" + } +}); \ No newline at end of file diff --git a/source/function/package.js b/source/function/package.js new file mode 100644 index 0000000..68a4c90 --- /dev/null +++ b/source/function/package.js @@ -0,0 +1,8 @@ +enyo.depends( + "to_do.js", + "weekly.js", + "calendar.js", + "to_do.css", + "calendar.css", + "weekly.css" +); \ No newline at end of file diff --git a/source/function/to_do.css b/source/function/to_do.css new file mode 100644 index 0000000..e492dd1 --- /dev/null +++ b/source/function/to_do.css @@ -0,0 +1,16 @@ + +.del_button{ + float: right; + height: 32px; + width: 32px; +} + +.ThingsCheckbox{ + float: left; + left: 5px; + vertical-align: middle; +} + +.ThingsCss{ + height: 35px; +} diff --git a/source/function/to_do.js b/source/function/to_do.js new file mode 100644 index 0000000..d69b034 --- /dev/null +++ b/source/function/to_do.js @@ -0,0 +1,114 @@ +enyo.kind({ + name: "To_do", + components:[ + {kind: "onyx.InputDecorator", style: "width: 100%;", components: [ + {kind: "onyx.Input", name:"to_do_input", classes: "Input", style: "width: 100%;", placeholder: "What do you need to do?", onkeypress:"inputChanged"} + ]}, + {tag: "br"}, + {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ + {kind: "onyx.GroupboxHeader", classes: "result_header", content: "To do Lists"}, + {name:"result_2", classes:"onyx-sample-result", content:"There is not things to do"} + ]} + ], + //by enter key, create new component + inputChanged: function(inSender, inEvent) { + if(inEvent.keyCode == 13){ + var count = parseInt(localStorage.count); + var Obj =[]; + count++; + localStorage.setItem('count', count); + Obj[count] = {number : count, state : 1, value : inSender.getValue()}; + localStorage.setItem(count, JSON.stringify(Obj[count])); + this.$.result_2.createComponent({kind:"Things", Things_content: inSender.getValue(), id: count}); + this.$.result_2.render(); + this.$.to_do_input.clear(); + } + }, + changeFocus: function(inSender, inEvent) { + enyo.forEach([this.$.inputDecorator, this.$.inputDecorator2, this.$.inputDecorator3], function(inItem) { + inItem.setAlwaysLooksFocused(inSender.getValue()); + // If disabling alwaysLooksFocused, we need to blur the + // InputDecorator for the setting to go into effect + if (!inSender.getValue()) { + inItem.triggerHandler("onblur"); + } + }); + }, + + create: function(){ + //localStorage.clear(); + this.inherited(arguments); + if(!localStorage.count){ + localStorage.setItem('count','0'); + } + else{ + for(var i = 1; i < parseInt(localStorage.count)+1 ; i++){ + if(localStorage.getItem(i) != null){ + var Obj = {}; + Obj = JSON.parse(localStorage.getItem(i)); + this.$.result_2.createComponent({kind:"Things", Things_content: Obj.value, state: Obj.state, id: i }); + } + } + this.$.result_2.render(); + } + + } + +}); + + +enyo.kind({ + name: "Things", + classes: "ThingsCss", + kind: "onyx.Toolbar", + published:{ + "Things_content":"", + "state": 1 + }, + components:[ + {name: "ThingsCheck", kind:"onyx.Checkbox", onchange:"checkboxChanged", classes:"ThingsCheckbox"}, + {name: "ThingsName", content:"", classes: "ThingsContent"}, + {kind: "onyx.IconButton", src: "assets/delete_button.png", ontap:"iconTapped", classes:"del_button"} + ], + create: function(){ + this.inherited(arguments); + if(this.state != 1){ + this.$.ThingsCheck.active = true; + } + if(this.Things_content){ + this.Things_contentChanged(); + } + }, + Things_contentChanged: function(){ + this.$.ThingsName.setContent(this.Things_content); + if(this.$.ThingsCheck.active == true){ + this.$.ThingsName.applyStyle("text-decoration","line-through"); + } + }, + checkboxChanged: function(inSender, inEvent) { + if(inSender.getValue()){ + this.$.ThingsName.applyStyle("text-decoration","line-through"); + var Obj = {} + Obj = JSON.parse(localStorage.getItem(this.id)); + Obj.state = 0; + localStorage.setItem(this.id, JSON.stringify(Obj)); + } + else{ + this.$.ThingsName.applyStyle("text-decoration","none"); + var Obj = {}; + Obj = JSON.parse(localStorage.getItem(this.id)); + Obj.state = 1; + localStorage.setItem(this.id, JSON.stringify(Obj)); + } + }, + iconTapped: function(inSender, inEvent){ + var parent = this.parent; + this.destroy(); + parent.render(); + }, + + destroy: function(){ + localStorage.removeItem(this.id); + this.inherited(arguments); + } +}); \ No newline at end of file diff --git a/source/function/weekly.css b/source/function/weekly.css new file mode 100644 index 0000000..493a1d5 --- /dev/null +++ b/source/function/weekly.css @@ -0,0 +1,93 @@ +.weekly { + padding: 0 20px; + font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; + font-size: 14px; +} +.weekly table { + width: 100%; + height: 90%; + border-collapse: collapse; +} +.weekly td.header { + padding: 5px 2px; + width: 14%; + height: 16px; + font-weight: bold; + text-transform: uppercase; + text-align: center; +} +.weekly td:first-of-type.header { + color: red; +} + +.weekly td:last-of-type.header { + color: blue; +} + +.weekly td { + padding: 2px; + vertical-align: top; + border: 1px solid #999; + background-color: #FFF; +} +.weekly td.current { + background-color: #226B9A; + color: #FFF; + padding: 5px 2px; + width: 14%; + height: 16px; + font-weight: bold; + text-transform: uppercase; + text-align: center; +} + +.weekly td.currentTime { + background-color: #226B9A; + color: #FFF; +} + + +.weekly .section { + padding-top: 20px; + font-size: 20px; + color: #000000; + display: block; + text-transform: uppercase; + font-weight: bold; + margin-bottom: 8px; + text-align: center; +} +.weekly .results { + margin: 20px 0; + padding: 20px; + min-height: 24px; + border-radius: 10px; + color: #FFF; + background-color: #555; +} + +.weekly .prev_button{ + float: left; +} + +.weekly .next_button{ + float: right; +} + +.contentSection{ + display: inline; +} + +.popupButton{ + float: right; +} + +.Typing{ + width: 115px; + height: 25px; + text-align: center; +} + +.inputContainer{ + display: inline-flex; +} \ No newline at end of file diff --git a/source/function/weekly.js b/source/function/weekly.js new file mode 100644 index 0000000..08aa626 --- /dev/null +++ b/source/function/weekly.js @@ -0,0 +1,526 @@ +enyo.kind({ + name: "weekly", + classes: "weekly enyo-fit", + components: [ + {name: "week", classes: "section", components:[ + {kind: "onyx.IconButton", src: "assets/left_arrow.png", ontap:"leftTapped", classes:"prev_button"}, + {name: "weekNumber", classes: "contentSection", ontap: "weekTapped", popup: "popupInput"}, + {name: "popupInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components:[ + {classes:"inputContainer", components:[ + {name: "yearInput", kind: "onyx.Input", placeholder: "Type Year here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, + {content: "년", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, + {name: "weekInput", kind: "onyx.Input", placeholder: "Type Week here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, + {content: "주", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, + ]}, + {tag: "br"}, + {tag: "br"}, + {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, + {kind: "onyx.Button", content: "Apply", ontap: "ApplyYearWeek", classes: "popupButton", popup: "showMessage"}, + {name: "showMessage", kind: "onyx.Popup", onkeypress:"closeMessagePopup2", centered: true, modal: true, floating: true, components:[ + {name:"popupContents", content:"", allowHtml: true, style:"text-align: center"}, + {tag: "br"}, + {kind:"onyx.Button", content: "Close", ontap: "closeMessagePopup", style:"position:relative; left: 50%; margin-left: -39.5px"} + ]} + ]}, + {kind: "onyx.IconButton", src: "assets/right_arrow.png", ontap:"rightTapped", classes:"next_button"} + ]}, + {name: "weekTable", kind: "enyo.Table", components: [ + + ]} + ], + published:{ + "setYear":"", + "setWeek":"" + }, + create: function() { + if(!localStorage.count_w){ + localStorage.setItem('count_w', '0'); + } + this.inherited(arguments); + var currentRow, + dateObj = new Date(); + + this.setYear = dateObj.getFullYear(); + this.setWeek = this.getWeekNumber(this.setYear, dateObj.getMonth(), dateObj.getDate()); + + var currentDate = dateObj.getDate(); + var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + var dayOffset = dateObj.getDay(); + var sundayDate = currentDate - dayOffset; + + for( var i = 0; i < 7; i++){ + if(i %7 == 0){ + currentRow = this.$.weekTable.createComponent({}); + } + + if(sundayDate < 1){ + sundayDate += this.getDaysInMonth(dateObj.getMonth()-1, dateObj.getYear()); + } + if(sundayDate + i > this.getDaysInMonth(dateObj.getMonth(), dateObj.getYear())){ + sundayDate -= this.getDaysInMonth(dateObj.getMonth(), dateObj.getYear()); + } + var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; + cellDay = enyo.mixin(cellDay, {classes: "header"}); + if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + for (var i = 0; i < 24; i++){ + currentRow = this.$.weekTable.createComponent({}); + for(var j = 0; j < 7 ; j++){ + var cellTime = new functionCell_W(); + cellTime.number = ((i<19)?i:(i-24)) + 5; + cellTime.year = this.setYear; + cellTime.week = this.setWeek; + cellTime.day = j; + if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) + } + currentRow.createComponent(cellTime); + } + } + + this.$.weekNumber.setContent(this.setYear + "년 " + this.setWeek + "주"); + }, + // adapted from http://stackoverflow.com/questions/1810984/number-of-days-in-any-month + getDaysInMonth: function(m, y) { + return (/8|3|5|10/).test(m)?30:m==1?((y%4===0)&&y%100)||(y%400===0)?29:28:31; + }, + getWeekNumber: function(year, month, date){ + d = new Date(); + d.setHours(0,0,0); + d.setFullYear(year, month, date); + // Set to nearest Thursday: current date + 4 - current day number + // Make Sunday's day number 7 + d.setDate(d.getDate() + 4 - (d.getDay()||7)); + // Get first day of yearc + var yearStart = new Date(year,0,1); + // Calculate full weeks to nearest Thursday + var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7); + // Return array of year and week number + if(yearStart.getDay() == 6){ + if((this.getDaysInMonth( 1, year) == 29) && (month == 11) && (date == 31)){ + return weekNo +2; + } + return weekNo +1; + } + else{ + return weekNo; + } + }, + + leftTapped: function(inSender, inEvent){ + this.$.weekTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + + // calculate current date + var currentDate = dateObj.getDate(); + var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + this.setWeek -= 1; + if(this.setWeek < 1){ + var lastWeek = new Date(); + lastWeek.setFullYear((this.setYear-1), 11, 31); + var lastWeekFirstDate = lastWeek.getDate() - lastWeek.getDay(); + firstWeek = new Date(); + firstWeek.setFullYear(this.setYear, 0, 1); + var firstWeekFirstDate = firstWeek.getDate() - ((firstWeek.getDay() == 0)? firstWeek.getDay() : (firstWeek.getDay() - 31)); + if(lastWeekFirstDate == firstWeekFirstDate){ + this.setWeek = this.getWeekNumber(lastWeek.getFullYear(), lastWeek.getMonth(), lastWeek.getDate()) - 1; + } + else { + this.setWeek = this.getWeekNumber(lastWeek.getFullYear(), lastWeek.getMonth(), lastWeek.getDate()); + } + this.setYear -= 1; + } + var yearStart = new Date(this.setYear, 0, 1); + var firstSunday = yearStart.getDate() - yearStart.getDay(); + if(firstSunday < 1 ){ + firstSunday += 31; + } + var sundayDate = firstSunday; + var count = 12; + for(var i = 1; i < this.setWeek ; i++){ + sundayDate += 7; + if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ + sundayDate -= this.getDaysInMonth(count%12, this.setYear); + count++; + } + } + for( var i = 0; i < 7; i++){ + if(i %7 == 0){ + currentRow = this.$.weekTable.createComponent({}); + } + + if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ + sundayDate -= this.getDaysInMonth(count, this.setYear); + } + var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; + cellDay = enyo.mixin(cellDay, {classes: "header"}); + if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + for (var i = 0; i < 24; i++){ + currentRow = this.$.weekTable.createComponent({}); + for(var j = 0; j < 7 ; j++){ + var cellTime = new functionCell_W(); + cellTime.number = ((i<19)?i:(i-24)) + 5; + cellTime.year = this.setYear; + cellTime.week = this.setWeek; + cellTime.day = j; + if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) + } + currentRow.createComponent(cellTime); + } + } + + + this.$.weekNumber.setContent(this.setYear + "년 " + this.setWeek + "주"); + this.$.weekTable.render(); + }, + + rightTapped: function(inSender, inEvent){ + this.$.weekTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + + // calculate current date + var currentDate = dateObj.getDate(); + var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + this.setWeek += 1; + if(this.setWeek == 53){ + var yearStart = new Date(this.setYear, 0, 1); + var firstSunday = yearStart.getDate() - yearStart.getDay(); + if(firstSunday < 1 ){ + firstSunday += 31; + } + var sundayDate = firstSunday; + var count = 12; + for(var i = 1; i < this.setWeek ; i++){ + sundayDate += 7; + if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ + sundayDate -= this.getDaysInMonth(count%12, this.setYear); + count++; + } + } + firstWeek = new Date(); + firstWeek.setFullYear((this.setYear+1), 0, 1); + var firstWeekFirstDate = firstWeek.getDate() - ((firstWeek.getDay() == 0)? firstWeek.getDay() : (firstWeek.getDay() - 31)); + if(sundayDate == firstWeekFirstDate){ + this.setWeek = 1; + this.setYear += 1; + } + } + else if(this.setWeek == 54){ + this.setWeek = 1; + this.setYear += 1; + } + var yearStart = new Date(this.setYear, 0, 1); + var firstSunday = yearStart.getDate() - yearStart.getDay(); + if(firstSunday < 1 ){ + firstSunday += 31; + } + var sundayDate = firstSunday; + var count = 12; + for(var i = 1; i < this.setWeek ; i++){ + sundayDate += 7; + if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ + sundayDate -= this.getDaysInMonth(count%12, this.setYear); + count++; + } + } + for( var i = 0; i < 7; i++){ + if(i %7 == 0){ + currentRow = this.$.weekTable.createComponent({}); + } + + if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ + sundayDate -= this.getDaysInMonth(count, this.setYear); + } + var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; + cellDay = enyo.mixin(cellDay, {classes: "header"}); + if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + for (var i = 0; i < 24; i++){ + currentRow = this.$.weekTable.createComponent({}); + for(var j = 0; j < 7 ; j++){ + var cellTime = new functionCell_W(); + cellTime.number = ((i<19)?i:(i-24)) + 5; + cellTime.year = this.setYear; + cellTime.week = this.setWeek; + cellTime.day = j; + if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) + } + currentRow.createComponent(cellTime); + } + } + + + this.$.weekNumber.setContent(this.setYear + " 년 " + this.setWeek + " 주"); + this.$.weekTable.render(); + }, + + weekTapped: function(inSender, inEvent){ + this.$.popupInput.show(); + }, + + closePopup: function(inSender, inEvent){ + this.$.popupInput.hide(); + }, + + closeMessagePopup: function(inSender, inEvent){ + this.$.showMessage.hide(); + }, + + popupShown: function() { + this.$.yearInput.focus(); + }, + + isInt: function(value){ + return typeof(value) === 'number' && value % 1 == 0; + }, + + ApplyYearWeek: function(inSender, inEvent){ + var yearInputValue = parseFloat(this.$.yearInput.getValue()); + var weekInputValue = parseFloat(this.$.weekInput.getValue()); + if(this.$.yearInput.getValue() == ""){ + this.$.popupContents.setContent("please input Year value!"); + this.$.showMessage.show(); + return; + } + if(this.$.weekInput.getValue() == ""){ + this.$.popupContents.setContent("please input Week value!"); + this.$.showMessage.show(); + return; + } + if(this.isInt(yearInputValue) == false){ + this.$.popupContents.setContent("Invalid Year value!
    please input integer value"); + this.$.showMessage.show(); + return; + } + else if(yearInputValue < 1000 || yearInputValue > 3000){ + this.$.popupContents.setContent("Invalid Year value!
    please input value between 1000 ~ 3000"); + this.$.showMessage.show(); + return; + } + this.setYear = yearInputValue; + if(this.isInt(weekInputValue) == false){ + this.$.popupContents.setContent("Invalid Week value!
    please input integer value"); + this.$.showMessage.show(); + return; + } + else if(weekInputValue < 1 || weekInputValue > this.getWeekNumber(this.setYear, 11, 31)){ + this.$.popupContents.setContent("Invalid Week value!
    please input value between 1 ~ " + this.getWeekNumber(this.setYear, 11, 31)); + this.$.showMessage.show(); + return; + } + this.setWeek = weekInputValue; + this.$.yearInput.clear(); + this.$.weekInput.clear(); + this.$.popupInput.hide(); + this.$.weekTable.destroyComponents(); + var currentRow, + dateObj = new Date(); + + // calculate current date + var currentDate = dateObj.getDate(); + var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + var yearStart = new Date(this.setYear, 0, 1); + var firstSunday = yearStart.getDate() - yearStart.getDay(); + if(firstSunday < 1 ){ + firstSunday += 31; + } + var sundayDate = firstSunday; + var count = 12; + for(var i = 1; i < this.setWeek ; i++){ + sundayDate += 7; + if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ + sundayDate -= this.getDaysInMonth(count%12, this.setYear); + count++; + } + } + for( var i = 0; i < 7; i++){ + if(i %7 == 0){ + currentRow = this.$.weekTable.createComponent({}); + } + + if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ + sundayDate -= this.getDaysInMonth(count, this.setYear); + } + var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; + cellDay = enyo.mixin(cellDay, {classes: "header"}); + if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellDay = enyo.mixin(cellDay, {classes: "current"}); + } + currentRow.createComponent(cellDay); + } + for (var i = 0; i < 24; i++){ + currentRow = this.$.weekTable.createComponent({}); + for(var j = 0; j < 7 ; j++){ + var cellTime = new functionCell_W(); + cellTime.number = ((i<19)?i:(i-24)) + 5; + cellTime.year = this.setYear; + cellTime.week = this.setWeek; + cellTime.day = j; + if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ + cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) + } + currentRow.createComponent(cellTime); + } + } + + + this.$.weekNumber.setContent(this.setYear + " 년 " + this.setWeek + " 주"); + this.$.weekTable.render(); + }, + + enterDetected: function(inSender, inEvent){ + if(inEvent.keyCode == 13){ + this.ApplyYearWeek(); + } + }, + + closeMessagePopup2: function(inSender,inEvent){ + if(inEvent.keyCode == 13){ + this.closeMessagePopup(); + } + } +}); + +enyo.kind({ + name:"functionCell_W", + kind:"enyo.TableCell", + components:[ + {name: "cellContent", popup:"scheduleInput", popup:"scheduleShow", content:"", style:"display:inline"}, + {name:"scheduleInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "", components:[ + {content: "제목", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, + {name: "subjectInput", kind: "onyx.Input", placeholder: "Type subject here", classes:"Typing", style: "margin: 10px", onkeypress:""}, + {tag:"br"}, + {content: "장소", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, + {name: "placeInput", kind: "onyx.Input", placeholder: "Type Place here", classes:"Typing", style: "margin: 10px", onkeypress:""}, + {tag:"br"}, + {tag:"br"}, + {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, + {kind: "onyx.Button", content: "Apply", ontap: "applySchedule", classes: "popupButton"} + ]}, + {name:"scheduleShow", kind:"onyx.Popup", onHide:"ScheduleListHide", modal: true, floating: true, components:[ + {kind: "onyx.Groupbox", components: [ + {name:"scheduleList", kind: "onyx.GroupboxHeader", content: "Schedule List"} + ]} + ]}, + {name: "scheduleImage", kind:"enyo.Image", src:"assets/dot.png", active: false, style:"float: right; height: 10px; width: 10px;"}, + {name: "schedule", components:[ + {name:"subject", content:""}, + {name:"time", content:""}, + {name:"place", content:""} + ]} + ], + published:{ + active: false, + isSchedule: false, + number: "", + year: "", + week: "", + day: "" + }, + handlers:{ + ontap:"cellTap", + onleave: "cellDeactive" + }, + create: function(){ + this.inherited(arguments); + this.$.cellContent.setContent(this.number); + + for(var i = 1 ; i < parseInt(localStorage.count_w)+1 ; i++){ + if((localStorage.getItem(i.toString()+'w')) != null){ + var Obj = {}; + Obj = JSON.parse(localStorage.getItem(i.toString()+'w')); + if(Obj.year == this.year && Obj.week == this.week && Obj.day == this.day && Obj.hours == this.number){ + this.restoreSchedule(Obj.subject, Obj.time, Obj.place); + } + } + } + + this.$.schedule.hide(); + if(this.isSchedule == false){ + this.$.scheduleImage.hide(); + } + }, + restoreSchedule: function(subject, time, place){ + var newSchedule = new scheduleThing(); + newSchedule.setContent(time + "시에 " + place + "에서 " + subject +"이(가) 있습니다."); + this.$.scheduleList.createComponent(newSchedule); + this.$.scheduleList.render(); + this.isSchedule = true; + this.$.scheduleImage.show(); + }, + cellTap: function(inSender, inEvent){ + if(this.active == false){ + this.active = true; + this.applyStyle("background-color","yellow"); + if(this.isSchedule == true){ + this.$.scheduleShow.showAtEvent(inEvent); + } + } + else if(this.active == true){ + this.$.scheduleInput.show(); + } + }, + cellDeactive: function(inSender, inEvent){ + if(this.active == true){ + this.active = false; + this.applyStyle("background-color", "white"); + if(this.getClassAttribute() == "currentTime"){ + this.applyStyle("background-color", "#226B9A"); + } + } + }, + closePopup: function(inSender, inEvent){ + this.$.scheduleInput.hide(); + }, + + applySchedule: function(inSender, inEvent){ + var subject = this.$.subjectInput.getValue(); + var time = this.$.cellContent.getContent(); + var place = this.$.placeInput.getValue(); + this.$.subjectInput.clear(); + this.$.placeInput.clear(); + + var newSchedule = new scheduleThing(); + newSchedule.setContent(time + "시에 " + place + "에서 " + subject +"이(가) 있습니다."); + var count_w = parseInt(localStorage.count_w); + count_w++; + localStorage.setItem('count_w', count_w); + var Obj_w = []; + Obj_w[count_w] = {year: this.year, week: this.week, day: this.day, hours: this.number, subject: subject, time: time, place: place }; + localStorage.setItem(count_w.toString() + 'w', JSON.stringify(Obj_w[count_w])); + this.$.scheduleList.createComponent(newSchedule); + this.$.scheduleList.render(); + this.isSchedule = true; + this.$.scheduleImage.show(); + this.$.scheduleInput.hide(); + }, + + ScheduleListHide: function(inSender, inEvent){ + if(this.active == false){ + this.active = true; + this.applyStyle("background-color","yellow"); + } + } +}); + +enyo.kind({ + name: "scheduleThing", + content: "", + handlers:{ + ontap: "editSchedule" + } +}); \ No newline at end of file diff --git a/source/package.js b/source/package.js new file mode 100644 index 0000000..7da252c --- /dev/null +++ b/source/package.js @@ -0,0 +1,8 @@ +enyo.depends( + "$lib/layout", + "$lib/onyx", // To theme Onyx using Theme.less, change this line to $lib/onyx/source, + //"Theme.less", // uncomment this line, and follow the steps described in Theme.less + "Scheduler.css", + "Scheduler.js", + "function" +); diff --git a/tools/deploy.bat b/tools/deploy.bat new file mode 100644 index 0000000..3138635 --- /dev/null +++ b/tools/deploy.bat @@ -0,0 +1,37 @@ +@REM don't watch the sausage being made +@ECHO OFF + +REM the folder this script is in (*/bootplate/tools) +SET TOOLS=%~DP0 + +REM enyo location +SET ENYO=%TOOLS%\..\enyo + +REM deploy script location +SET DEPLOY=%ENYO%\tools\deploy.js + +REM node location +SET NODE=node.exe + +REM use node to invoke deploy.js with imported parameters +%NODE% "%DEPLOY%" %* + +REM copy files and package if deploying to cordova webos +:again +if not "%1" == "" ( + + if "%1" == "--cordova-webos" ( + REM copy appinfo.json and cordova*.js files + SET SRC=%TOOLS%..\ + for %%A in ("%~dp0./..") do SET DEST=%TOOLS%..\deploy\%%~nA + copy %SRC%appinfo.json %DEST% + copy %SRC%cordova*.js %DEST% + + REM package it up + if not exist %SRC%bin mkdir %SRC%bin + palm-package.bat %DEST% --outdir=%SRC%bin + ) + + shift + goto again +) diff --git a/tools/deploy.sh b/tools/deploy.sh new file mode 100644 index 0000000..e9af9fd --- /dev/null +++ b/tools/deploy.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# the folder this script is in (*/bootplate/tools) +TOOLS=$(cd `dirname $0` && pwd) + +# enyo location +ENYO="$TOOLS/../enyo" + +# deploy script location +DEPLOY="$ENYO/tools/deploy.js" + +# check for node, but quietly +if command -v node >/dev/null 2>&1; then + # use node to invoke deploy with imported parameters + echo "enyo/tools/minify.sh args: " $@ + node "$DEPLOY" $@ +else + echo "No node found in path" + exit 1 +fi + +# copy files and package if deploying to cordova webos +while [ "$1" != "" ]; do + case $1 in + -w | --cordova-webos ) + # copy appinfo.json and cordova*.js files + SRC="$TOOLS/../" + DEST="$TOOLS/../deploy/"${PWD##*/} + + cp "$SRC"appinfo.json $DEST -v + cp "$SRC"cordova*.js $DEST -v + + # package it up + mkdir -p "$DEST/bin" + palm-package "$DEST/bin" + ;; + esac + shift +done From 0ea221d8ddb5ba5dfc600bcc15fdac4e3c9f098b Mon Sep 17 00:00:00 2001 From: Saramean Date: Fri, 20 Jun 2014 16:47:38 +0900 Subject: [PATCH 2/3] Revert "Saramean scheduler" This reverts commit 2d8e79889c3557bea7e07e14b3304f4163ed2734. --- README-CORDOVA-WEBOS.md | 8 - README.md | 65 +- api/assets/busy.gif | Bin 310 -> 0 bytes api/assets/favicon.ico | Bin 1150 -> 0 bytes api/assets/manifest.json | 13 - api/assets/search-input-search.png | Bin 447 -> 0 bytes api/build/app.css | 889 ---- api/build/app.js | 4372 ---------------- api/build/enyo.css | 181 - api/build/enyo.js | 4283 ---------------- api/icon.png | Bin 7115 -> 0 bytes api/index.html | 23 - assets/Diary.png | Bin 7666 -> 0 bytes assets/check.png | Bin 13502 -> 0 bytes assets/delete_button.png | Bin 4767 -> 0 bytes assets/dot.png | Bin 6489 -> 0 bytes assets/favicon.ico | Bin 1150 -> 0 bytes assets/left_arrow.png | Bin 3673 -> 0 bytes assets/month.png | Bin 26463 -> 0 bytes assets/right_arrow.png | Bin 3676 -> 0 bytes assets/week.png | Bin 60585 -> 0 bytes build/app.css | 1432 ------ build/app.js | 4447 ----------------- build/enyo.css | 181 - build/enyo.js | 4308 ---------------- debug.html | 23 - deploy.md | 52 - deploy/bootplate/assets/favicon.ico | Bin 1150 -> 0 bytes deploy/bootplate/build/app.css | 1432 ------ deploy/bootplate/build/app.js | 4447 ----------------- deploy/bootplate/build/enyo.css | 181 - deploy/bootplate/build/enyo.js | 4283 ---------------- deploy/bootplate/icon.png | Bin 7115 -> 0 bytes deploy/bootplate/index.html | 27 - deploy/bootplate/lib/onyx/LICENSE-2.0.txt | 202 - deploy/bootplate/lib/onyx/images/checkbox.png | Bin 5462 -> 0 bytes .../bootplate/lib/onyx/images/grabbutton.png | Bin 676 -> 0 bytes .../lib/onyx/images/gradient-invert.png | Bin 255 -> 0 bytes deploy/bootplate/lib/onyx/images/gradient.png | Bin 255 -> 0 bytes deploy/bootplate/lib/onyx/images/more.png | Bin 2696 -> 0 bytes .../onyx/images/progress-button-cancel.png | Bin 2631 -> 0 bytes .../lib/onyx/images/search-input-cancel.png | Bin 303 -> 0 bytes .../lib/onyx/images/search-input-search.png | Bin 447 -> 0 bytes .../lib/onyx/images/slider-handle.png | Bin 3095 -> 0 bytes .../lib/onyx/images/spinner-dark.gif | Bin 1924 -> 0 bytes .../lib/onyx/images/spinner-light.gif | Bin 1924 -> 0 bytes enyo/CONTRIBUTING md | 10 - enyo/LICENSE-2.0.txt | 202 - enyo/README.md | 146 - enyo/enyo.js | 41 - enyo/loader.js | 302 -- enyo/minify/minify.bat | 6 - enyo/minify/minify.sh | 3 - enyo/minify/package.js | 4 - enyo/package.json | 19 - enyo/samples/AjaxSample.css | 14 - enyo/samples/AjaxSample.html | 21 - enyo/samples/AjaxSample.js | 37 - enyo/samples/GestureSample.css | 57 - enyo/samples/GestureSample.html | 21 - enyo/samples/GestureSample.js | 198 - enyo/samples/JsonpSample.css | 14 - enyo/samples/JsonpSample.html | 21 - enyo/samples/JsonpSample.js | 29 - enyo/samples/PlatformSample.css | 11 - enyo/samples/PlatformSample.html | 21 - enyo/samples/PlatformSample.js | 36 - enyo/samples/Playground.css | 29 - enyo/samples/Playground.html | 23 - enyo/samples/Playground.js | 54 - enyo/samples/RepeaterSample.css | 9 - enyo/samples/RepeaterSample.html | 21 - enyo/samples/RepeaterSample.js | 52 - enyo/samples/ScrollerSample.css | 9 - enyo/samples/ScrollerSample.html | 21 - enyo/samples/ScrollerSample.js | 78 - enyo/samples/WebServiceSample.css | 14 - enyo/samples/WebServiceSample.html | 21 - enyo/samples/WebServiceSample.js | 32 - enyo/samples/assets/Sample1.js | 15 - enyo/samples/assets/Sample2.js | 15 - enyo/samples/assets/Sample3.js | 30 - enyo/samples/assets/Sample4.js | 24 - enyo/samples/package.js | 19 - enyo/source/ajax/Ajax.js | 255 - enyo/source/ajax/AjaxProperties.js | 68 - enyo/source/ajax/Async.js | 128 - enyo/source/ajax/Jsonp.js | 123 - enyo/source/ajax/WebService.js | 114 - enyo/source/ajax/cookie.js | 50 - enyo/source/ajax/formdata.js | 91 - enyo/source/ajax/json.js | 21 - enyo/source/ajax/package.js | 11 - enyo/source/ajax/xhr.js | 143 - enyo/source/boot/boot.js | 133 - enyo/source/boot/enyo.js | 31 - enyo/source/boot/package.js | 5 - enyo/source/dom/Control.js | 879 ---- enyo/source/dom/animation.js | 99 - enyo/source/dom/dispatcher.js | 177 - enyo/source/dom/dom.css | 100 - enyo/source/dom/dom.js | 231 - enyo/source/dom/drag.js | 266 - enyo/source/dom/gesture.js | 172 - enyo/source/dom/modal.js | 49 - enyo/source/dom/package.js | 15 - enyo/source/dom/phonegap.js | 46 - enyo/source/dom/platform.js | 90 - enyo/source/dom/preview.js | 36 - enyo/source/dom/transform.js | 139 - enyo/source/dom/transition.js | 5 - enyo/source/kernel/Component.js | 547 -- enyo/source/kernel/Layout.js | 34 - enyo/source/kernel/Object.js | 143 - enyo/source/kernel/Oop.js | 218 - enyo/source/kernel/Signals.js | 44 - enyo/source/kernel/UiComponent.js | 316 -- enyo/source/kernel/job.js | 33 - enyo/source/kernel/lang.js | 416 -- enyo/source/kernel/log.js | 98 - enyo/source/kernel/macroize.js | 74 - enyo/source/kernel/package.js | 12 - enyo/source/package.js | 7 - enyo/source/touch/ScrollMath.js | 305 -- enyo/source/touch/ScrollStrategy.js | 186 - enyo/source/touch/Scroller.css | 19 - enyo/source/touch/Scroller.js | 344 -- enyo/source/touch/Thumb.css | 22 - enyo/source/touch/Thumb.js | 111 - enyo/source/touch/TouchScrollStrategy.js | 429 -- enyo/source/touch/TransitionScrollStrategy.js | 616 --- enyo/source/touch/TranslateScrollStrategy.js | 157 - enyo/source/touch/gesture.js | 130 - enyo/source/touch/msevents.js | 93 - enyo/source/touch/package.js | 14 - enyo/source/touch/touch.js | 139 - enyo/source/ui/Animator.js | 132 - enyo/source/ui/BaseLayout.js | 22 - enyo/source/ui/Button.js | 42 - enyo/source/ui/Checkbox.js | 77 - enyo/source/ui/DragAvatar.js | 90 - enyo/source/ui/FloatingLayer.js | 38 - enyo/source/ui/Group.js | 46 - enyo/source/ui/GroupItem.js | 28 - enyo/source/ui/Image.js | 28 - enyo/source/ui/Input.js | 148 - enyo/source/ui/Popup.js | 303 -- enyo/source/ui/Repeater.js | 108 - enyo/source/ui/RichText.js | 138 - enyo/source/ui/Select.js | 116 - enyo/source/ui/Selection.js | 171 - enyo/source/ui/Table.js | 36 - enyo/source/ui/TextArea.js | 20 - enyo/source/ui/ToolDecorator.js | 9 - enyo/source/ui/package.js | 21 - enyo/source/ui/ui.css | 26 - enyo/tools/README.md | 23 - enyo/tools/deploy.js | 230 - enyo/tools/lessc.bat | 17 - enyo/tools/lessc.sh | 18 - enyo/tools/minifier/lessc.js | 80 - enyo/tools/minifier/minify.js | 231 - .../minifier/node_modules/less/CHANGELOG.md | 49 - enyo/tools/minifier/node_modules/less/LICENSE | 179 - .../tools/minifier/node_modules/less/Makefile | 76 - .../minifier/node_modules/less/README.md | 28 - .../less/benchmark/benchmark.less | 3979 --------------- .../less/benchmark/less-benchmark.js | 47 - .../minifier/node_modules/less/bin/lessc | 160 - .../minifier/node_modules/less/build/amd.js | 6 - .../node_modules/less/build/ecma-5.js | 120 - .../node_modules/less/build/header.js | 7 - .../node_modules/less/build/require-rhino.js | 7 - .../node_modules/less/build/require.js | 7 - .../node_modules/less/dist/less-1.1.0.js | 2695 ---------- .../node_modules/less/dist/less-1.1.0.min.js | 16 - .../node_modules/less/dist/less-1.1.1.js | 2710 ---------- .../node_modules/less/dist/less-1.1.1.min.js | 16 - .../node_modules/less/dist/less-1.1.2.js | 2712 ---------- .../node_modules/less/dist/less-1.1.2.min.js | 16 - .../node_modules/less/dist/less-1.1.3.js | 2721 ---------- .../node_modules/less/dist/less-1.1.3.min.js | 16 - .../node_modules/less/dist/less-1.1.4.js | 2769 ---------- .../node_modules/less/dist/less-1.1.4.min.js | 16 - .../node_modules/less/dist/less-1.1.5.js | 2805 ----------- .../node_modules/less/dist/less-1.1.5.min.js | 9 - .../node_modules/less/dist/less-1.1.6.js | 3004 ----------- .../node_modules/less/dist/less-1.1.6.min.js | 9 - .../node_modules/less/dist/less-1.2.0.js | 3293 ------------ .../node_modules/less/dist/less-1.2.0.min.js | 9 - .../node_modules/less/dist/less-1.2.1.js | 3318 ------------ .../node_modules/less/dist/less-1.2.1.min.js | 9 - .../node_modules/less/dist/less-1.2.2.js | 3337 ------------- .../node_modules/less/dist/less-1.2.2.min.js | 9 - .../node_modules/less/dist/less-1.3.0.js | 3478 ------------- .../node_modules/less/dist/less-1.3.0.min.js | 9 - .../node_modules/less/dist/less-1.3.0e.js | 4017 --------------- .../node_modules/less/dist/less-1.3.0e.min.js | 9 - .../less/dist/less-rhino-1.1.3.js | 2460 --------- .../less/dist/less-rhino-1.1.5.js | 2481 --------- .../node_modules/less/lib/less/browser.js | 394 -- .../node_modules/less/lib/less/colors.js | 152 - .../node_modules/less/lib/less/cssmin.js | 355 -- .../node_modules/less/lib/less/functions.js | 337 -- .../node_modules/less/lib/less/index.js | 140 - .../less/lib/less/lessc_helper.js | 59 - .../node_modules/less/lib/less/parser.js | 1445 ------ .../node_modules/less/lib/less/rhino.js | 123 - .../node_modules/less/lib/less/tree.js | 43 - .../node_modules/less/lib/less/tree/alpha.js | 17 - .../less/lib/less/tree/anonymous.js | 27 - .../less/lib/less/tree/assignment.js | 19 - .../node_modules/less/lib/less/tree/call.js | 48 - .../node_modules/less/lib/less/tree/color.js | 111 - .../less/lib/less/tree/comment.js | 14 - .../less/lib/less/tree/condition.js | 42 - .../less/lib/less/tree/dimension.js | 49 - .../less/lib/less/tree/directive.js | 39 - .../less/lib/less/tree/element.js | 48 - .../less/lib/less/tree/expression.js | 23 - .../node_modules/less/lib/less/tree/import.js | 83 - .../less/lib/less/tree/javascript.js | 51 - .../less/lib/less/tree/keyword.js | 19 - .../node_modules/less/lib/less/tree/media.js | 123 - .../node_modules/less/lib/less/tree/mixin.js | 146 - .../less/lib/less/tree/operation.js | 32 - .../node_modules/less/lib/less/tree/paren.js | 16 - .../node_modules/less/lib/less/tree/quoted.js | 43 - .../node_modules/less/lib/less/tree/ratio.js | 13 - .../node_modules/less/lib/less/tree/rule.js | 42 - .../less/lib/less/tree/ruleset.js | 374 -- .../less/lib/less/tree/selector.js | 47 - .../node_modules/less/lib/less/tree/url.js | 29 - .../node_modules/less/lib/less/tree/value.js | 24 - .../less/lib/less/tree/variable.js | 26 - .../minifier/node_modules/less/package.json | 17 - .../node_modules/less/test/css/colors.css | 77 - .../node_modules/less/test/css/comments.css | 56 - .../node_modules/less/test/css/css-3.css | 98 - .../less/test/css/css-escapes.css | 24 - .../node_modules/less/test/css/css.css | 100 - .../less/test/css/debug/linenumbers-all.css | 39 - .../test/css/debug/linenumbers-comments.css | 32 - .../test/css/debug/linenumbers-mediaquery.css | 32 - .../node_modules/less/test/css/functions.css | 92 - .../node_modules/less/test/css/ie-filters.css | 9 - .../less/test/css/import-once.css | 6 - .../node_modules/less/test/css/import.css | 23 - .../node_modules/less/test/css/javascript.css | 23 - .../node_modules/less/test/css/lazy-eval.css | 3 - .../node_modules/less/test/css/media.css | 176 - .../less/test/css/mixins-args.css | 74 - .../less/test/css/mixins-closure.css | 9 - .../less/test/css/mixins-guards.css | 68 - .../less/test/css/mixins-important.css | 17 - .../less/test/css/mixins-named-args.css | 20 - .../less/test/css/mixins-nested.css | 14 - .../less/test/css/mixins-pattern.css | 47 - .../node_modules/less/test/css/mixins.css | 108 - .../node_modules/less/test/css/operations.css | 49 - .../node_modules/less/test/css/parens.css | 20 - .../node_modules/less/test/css/rulesets.css | 33 - .../node_modules/less/test/css/scope.css | 15 - .../node_modules/less/test/css/selectors.css | 130 - .../node_modules/less/test/css/strings.css | 40 - .../node_modules/less/test/css/variables.css | 27 - .../node_modules/less/test/css/whitespace.css | 42 - .../node_modules/less/test/less-test.js | 174 - .../node_modules/less/test/less/colors.less | 88 - .../node_modules/less/test/less/comments.less | 65 - .../node_modules/less/test/less/css-3.less | 108 - .../less/test/less/css-escapes.less | 33 - .../node_modules/less/test/less/css.less | 115 - .../less/test/less/debug/import/test.less | 23 - .../less/test/less/debug/linenumbers.less | 21 - .../test/less/errors/comment-in-selector.less | 1 - .../test/less/errors/comment-in-selector.txt | 2 - .../less/test/less/errors/import-missing.less | 1 - .../less/test/less/errors/import-missing.txt | 3 - .../less/test/less/errors/import-no-semi.less | 1 - .../less/test/less/errors/import-no-semi.txt | 2 - .../test/less/errors/import-subfolder1.less | 1 - .../test/less/errors/import-subfolder1.txt | 3 - .../test/less/errors/import-subfolder2.less | 1 - .../test/less/errors/import-subfolder2.txt | 2 - .../errors/imports/import-subfolder1.less | 1 - .../errors/imports/import-subfolder2.less | 1 - .../imports/subfolder/mixin-not-defined.less | 1 - .../subfolder/parse-error-curly-bracket.less | 1 - .../test/less/errors/javascript-error.less | 3 - .../test/less/errors/javascript-error.txt | 4 - .../test/less/errors/mixin-not-defined.less | 11 - .../test/less/errors/mixin-not-defined.txt | 3 - .../errors/parse-error-curly-bracket.less | 1 - .../less/errors/parse-error-curly-bracket.txt | 2 - .../errors/parse-error-missing-bracket.less | 2 - .../errors/parse-error-missing-bracket.txt | 2 - .../test/less/errors/property-ie5-hack.less | 3 - .../test/less/errors/property-ie5-hack.txt | 4 - .../less/test/less/functions.less | 101 - .../less/test/less/ie-filters.less | 15 - .../less/test/less/import-once.less | 3 - .../node_modules/less/test/less/import.less | 11 - .../import/deeper/import-once-test-a.less | 1 - .../test/less/import/import-once-test-c.less | 7 - .../less/test/less/import/import-test-a.less | 2 - .../less/test/less/import/import-test-b.less | 8 - .../less/test/less/import/import-test-c.less | 7 - .../less/test/less/import/import-test-d.css | 1 - .../less/test/less/import/import-test-e.less | 2 - .../less/test/less/javascript.less | 29 - .../less/test/less/lazy-eval.less | 6 - .../node_modules/less/test/less/media.less | 179 - .../less/test/less/mixins-args.less | 130 - .../less/test/less/mixins-closure.less | 26 - .../less/test/less/mixins-guards.less | 113 - .../less/test/less/mixins-important.less | 18 - .../less/test/less/mixins-named-args.less | 31 - .../less/test/less/mixins-nested.less | 22 - .../less/test/less/mixins-pattern.less | 99 - .../node_modules/less/test/less/mixins.less | 93 - .../less/test/less/operations.less | 62 - .../node_modules/less/test/less/parens.less | 26 - .../node_modules/less/test/less/rulesets.less | 30 - .../node_modules/less/test/less/scope.less | 32 - .../less/test/less/selectors.less | 131 - .../node_modules/less/test/less/strings.less | 51 - .../less/test/less/variables.less | 54 - .../less/test/less/whitespace.less | 44 - .../node_modules/uglify-js/.npmignore | 6 - .../node_modules/uglify-js/README.html | 981 ---- .../node_modules/uglify-js/README.org | 578 --- .../node_modules/uglify-js/bin/uglifyjs | 335 -- .../node_modules/uglify-js/docstyle.css | 75 - .../uglify-js/lib/consolidator.js | 1220 ----- .../node_modules/uglify-js/lib/parse-js.js | 1364 ----- .../node_modules/uglify-js/lib/process.js | 2091 -------- .../uglify-js/lib/squeeze-more.js | 74 - .../node_modules/uglify-js/package.json | 30 - .../node_modules/uglify-js/test/beautify.js | 28 - .../node_modules/uglify-js/test/testparser.js | 409 -- .../test/unit/compress/expected/array1.js | 1 - .../test/unit/compress/expected/array2.js | 1 - .../test/unit/compress/expected/array3.js | 1 - .../test/unit/compress/expected/array4.js | 1 - .../test/unit/compress/expected/assignment.js | 1 - .../unit/compress/expected/concatstring.js | 1 - .../test/unit/compress/expected/const.js | 1 - .../unit/compress/expected/empty-blocks.js | 1 - .../unit/compress/expected/forstatement.js | 1 - .../test/unit/compress/expected/if.js | 1 - .../test/unit/compress/expected/ifreturn.js | 1 - .../test/unit/compress/expected/ifreturn2.js | 1 - .../test/unit/compress/expected/issue10.js | 1 - .../test/unit/compress/expected/issue11.js | 1 - .../test/unit/compress/expected/issue13.js | 1 - .../test/unit/compress/expected/issue14.js | 1 - .../test/unit/compress/expected/issue16.js | 1 - .../test/unit/compress/expected/issue17.js | 1 - .../test/unit/compress/expected/issue20.js | 1 - .../test/unit/compress/expected/issue21.js | 1 - .../test/unit/compress/expected/issue25.js | 1 - .../test/unit/compress/expected/issue27.js | 1 - .../test/unit/compress/expected/issue278.js | 1 - .../test/unit/compress/expected/issue28.js | 1 - .../test/unit/compress/expected/issue29.js | 1 - .../test/unit/compress/expected/issue30.js | 1 - .../test/unit/compress/expected/issue34.js | 1 - .../test/unit/compress/expected/issue4.js | 1 - .../test/unit/compress/expected/issue48.js | 1 - .../test/unit/compress/expected/issue50.js | 1 - .../test/unit/compress/expected/issue53.js | 1 - .../test/unit/compress/expected/issue54.1.js | 1 - .../test/unit/compress/expected/issue68.js | 1 - .../test/unit/compress/expected/issue69.js | 1 - .../test/unit/compress/expected/issue9.js | 1 - .../test/unit/compress/expected/mangle.js | 1 - .../unit/compress/expected/null_string.js | 1 - .../unit/compress/expected/strict-equals.js | 1 - .../test/unit/compress/expected/var.js | 1 - .../test/unit/compress/expected/whitespace.js | 1 - .../test/unit/compress/expected/with.js | 1 - .../test/unit/compress/test/array1.js | 3 - .../test/unit/compress/test/array2.js | 4 - .../test/unit/compress/test/array3.js | 4 - .../test/unit/compress/test/array4.js | 6 - .../test/unit/compress/test/assignment.js | 20 - .../test/unit/compress/test/concatstring.js | 3 - .../test/unit/compress/test/const.js | 5 - .../test/unit/compress/test/empty-blocks.js | 4 - .../test/unit/compress/test/forstatement.js | 10 - .../uglify-js/test/unit/compress/test/if.js | 6 - .../test/unit/compress/test/ifreturn.js | 9 - .../test/unit/compress/test/ifreturn2.js | 16 - .../test/unit/compress/test/issue10.js | 1 - .../test/unit/compress/test/issue11.js | 3 - .../test/unit/compress/test/issue13.js | 1 - .../test/unit/compress/test/issue14.js | 1 - .../test/unit/compress/test/issue16.js | 1 - .../test/unit/compress/test/issue17.js | 4 - .../test/unit/compress/test/issue20.js | 1 - .../test/unit/compress/test/issue21.js | 6 - .../test/unit/compress/test/issue25.js | 7 - .../test/unit/compress/test/issue27.js | 1 - .../test/unit/compress/test/issue278.js | 1 - .../test/unit/compress/test/issue28.js | 3 - .../test/unit/compress/test/issue29.js | 1 - .../test/unit/compress/test/issue30.js | 3 - .../test/unit/compress/test/issue34.js | 3 - .../test/unit/compress/test/issue4.js | 3 - .../test/unit/compress/test/issue48.js | 1 - .../test/unit/compress/test/issue50.js | 9 - .../test/unit/compress/test/issue53.js | 1 - .../test/unit/compress/test/issue54.1.js | 3 - .../test/unit/compress/test/issue68.js | 5 - .../test/unit/compress/test/issue69.js | 1 - .../test/unit/compress/test/issue9.js | 4 - .../test/unit/compress/test/mangle.js | 5 - .../test/unit/compress/test/null_string.js | 1 - .../test/unit/compress/test/strict-equals.js | 3 - .../uglify-js/test/unit/compress/test/var.js | 3 - .../test/unit/compress/test/whitespace.js | 21 - .../uglify-js/test/unit/compress/test/with.js | 2 - .../uglify-js/test/unit/scripts.js | 57 - .../node_modules/uglify-js/tmp/hoist.js | 33 - .../node_modules/uglify-js/tmp/instrument.js | 97 - .../node_modules/uglify-js/tmp/test.js | 30 - .../node_modules/uglify-js/uglify-js.js | 18 - enyo/tools/minifier/node_modules/walker.js | 40 - enyo/tools/minifier/path-relative-shim.js | 135 - enyo/tools/minify.bat | 17 - enyo/tools/minify.sh | 18 - enyo/tools/node_modules/.bin/nopt | 44 - enyo/tools/node_modules/.bin/shjs | 43 - enyo/tools/node_modules/nopt/.npmignore | 0 enyo/tools/node_modules/nopt/LICENSE | 23 - enyo/tools/node_modules/nopt/README.md | 210 - enyo/tools/node_modules/nopt/bin/nopt.js | 44 - .../node_modules/nopt/examples/my-program.js | 30 - enyo/tools/node_modules/nopt/lib/nopt.js | 555 -- .../nopt/node_modules/abbrev/README.md | 23 - .../nopt/node_modules/abbrev/lib/abbrev.js | 106 - .../nopt/node_modules/abbrev/package.json | 20 - enyo/tools/node_modules/nopt/package.json | 31 - .../node_modules/shelljs/.documentup.json | 6 - enyo/tools/node_modules/shelljs/.travis.yml | 6 - enyo/tools/node_modules/shelljs/LICENSE | 26 - enyo/tools/node_modules/shelljs/README.md | 421 -- enyo/tools/node_modules/shelljs/bin/shjs | 43 - enyo/tools/node_modules/shelljs/global.js | 3 - enyo/tools/node_modules/shelljs/make.js | 46 - enyo/tools/node_modules/shelljs/package.json | 39 - .../node_modules/shelljs/scripts/docs.js | 15 - .../node_modules/shelljs/scripts/run-tests.js | 22 - enyo/tools/node_modules/shelljs/shell.js | 1513 ------ .../node_modules/shelljs/test/.npmignore | 2 - enyo/tools/node_modules/shelljs/test/cat.js | 57 - enyo/tools/node_modules/shelljs/test/cd.js | 64 - enyo/tools/node_modules/shelljs/test/cp.js | 130 - enyo/tools/node_modules/shelljs/test/echo.js | 50 - enyo/tools/node_modules/shelljs/test/env.js | 19 - enyo/tools/node_modules/shelljs/test/exec.js | 93 - enyo/tools/node_modules/shelljs/test/find.js | 56 - enyo/tools/node_modules/shelljs/test/grep.js | 59 - enyo/tools/node_modules/shelljs/test/ls.js | 202 - enyo/tools/node_modules/shelljs/test/mkdir.js | 79 - enyo/tools/node_modules/shelljs/test/mv.js | 130 - enyo/tools/node_modules/shelljs/test/pwd.js | 28 - .../node_modules/shelljs/test/resources/a.txt | 11 - .../node_modules/shelljs/test/resources/cp/a | 1 - .../node_modules/shelljs/test/resources/cp/b | 1 - .../shelljs/test/resources/cp/dir_a/z | 1 - .../resources/cp/dir_b/dir_b_a/dir_b_a_a/z | 1 - .../test/resources/external/node_script.js | 2 - .../test/resources/external/tmp/output | 0 .../test/resources/external/tmp/tempscript.js | 1 - .../node_modules/shelljs/test/resources/file1 | 1 - .../shelljs/test/resources/file1.js | 1 - .../shelljs/test/resources/file1.txt | 1 - .../node_modules/shelljs/test/resources/file2 | 1 - .../shelljs/test/resources/file2.js | 1 - .../shelljs/test/resources/file2.txt | 1 - .../shelljs/test/resources/find/.hidden | 1 - .../shelljs/test/resources/find/a | 1 - .../shelljs/test/resources/find/b | 1 - .../shelljs/test/resources/find/dir1/a_dir1 | 1 - .../test/resources/find/dir1/dir11/a_dir11 | 1 - .../shelljs/test/resources/find/dir2/a_dir1 | 1 - .../test/resources/ls/.hidden_dir/nada | 1 - .../shelljs/test/resources/ls/.hidden_file | 1 - .../test/resources/ls/a_dir/.hidden_dir/nada | 1 - .../shelljs/test/resources/ls/a_dir/b_dir/z | 1 - .../shelljs/test/resources/ls/a_dir/nada | 1 - .../shelljs/test/resources/ls/file1 | 1 - .../shelljs/test/resources/ls/file1.js | 1 - .../shelljs/test/resources/ls/file2 | 1 - .../shelljs/test/resources/ls/file2.js | 1 - ...ilename(with)[chars$]^that.must+be-escaped | 1 - enyo/tools/node_modules/shelljs/test/rm.js | 183 - enyo/tools/node_modules/shelljs/test/sed.js | 58 - .../tools/node_modules/shelljs/test/silent.js | 26 - .../node_modules/shelljs/test/tempdir.js | 27 - enyo/tools/node_modules/shelljs/test/test.js | 83 - enyo/tools/node_modules/shelljs/test/to.js | 39 - enyo/tools/node_modules/shelljs/test/which.js | 38 - enyo/tools/test/ajax/index.html | 13 - enyo/tools/test/ajax/package.js | 3 - enyo/tools/test/ajax/php/redball.jpg | Bin 396 -> 0 bytes enyo/tools/test/ajax/php/test1.php | 18 - enyo/tools/test/ajax/php/test2.php | 54 - enyo/tools/test/ajax/php/test3.php | 15 - enyo/tools/test/ajax/php/test4.php | 22 - enyo/tools/test/ajax/php/test5.php | 20 - enyo/tools/test/ajax/php/test6.php | 31 - enyo/tools/test/ajax/tests/AjaxTest.js | 246 - enyo/tools/test/ajax/tests/JsonpTest.js | 29 - enyo/tools/test/ajax/tests/WebServiceTest.js | 112 - enyo/tools/test/ajax/tests/XhrTest.js | 16 - enyo/tools/test/ajax/tests/package.js | 6 - enyo/tools/test/core/index.html | 15 - enyo/tools/test/core/test.css | 33 - enyo/tools/test/core/test.js | 303 -- enyo/tools/test/core/tests/AjaxTest.js | 53 - enyo/tools/test/core/tests/AsyncTest.js | 44 - .../test/core/tests/ComponentDispatchTest.js | 74 - .../test/core/tests/ComponentHandlersTest.js | 22 - enyo/tools/test/core/tests/ComponentTest.js | 28 - .../tools/test/core/tests/ControlPropsTest.js | 32 - enyo/tools/test/core/tests/ControlTest.js | 92 - .../test/core/tests/DecodePackagePathTest.js | 70 - enyo/tools/test/core/tests/JsonTest.js | 36 - enyo/tools/test/core/tests/KindTest.js | 41 - enyo/tools/test/core/tests/LoaderTest.js | 28 - .../tools/test/core/tests/PathResolverTest.js | 57 - .../core/tests/ViewportPositioningTest.js | 104 - enyo/tools/test/core/tests/langTest.js | 54 - enyo/tools/test/core/tests/loader1.js | 1 - enyo/tools/test/core/tests/loader2a.js | 1 - enyo/tools/test/core/tests/loader2b.js | 1 - enyo/tools/test/core/tests/package.js | 16 - gallery_images/Saramean.scheduler.jpg | Bin 37999 -> 0 bytes gallery_manifest.json | 23 - icon.png | Bin 7115 -> 0 bytes index.html | 131 +- lib/layout/CONTRIBUTING md | 10 - lib/layout/README.md | 71 - lib/layout/deploy.bat | 0 lib/layout/deploy.sh | 0 lib/layout/design.js | 155 - lib/layout/fittable/package.js | 3 - .../fittable/samples/FittableAppLayout1.html | 22 - .../fittable/samples/FittableAppLayout1.js | 21 - .../fittable/samples/FittableAppLayout2.html | 22 - .../fittable/samples/FittableAppLayout2.js | 25 - .../fittable/samples/FittableAppLayout3.html | 22 - .../fittable/samples/FittableAppLayout3.js | 20 - .../fittable/samples/FittableAppLayout4.html | 22 - .../fittable/samples/FittableAppLayout4.js | 21 - .../fittable/samples/FittableDescription.html | 21 - .../fittable/samples/FittableDescription.js | 44 - .../fittable/samples/FittableSample.html | 21 - lib/layout/fittable/samples/FittableSample.js | 22 - .../fittable/samples/FittableTests.html | 21 - lib/layout/fittable/samples/FittableTests.js | 84 - lib/layout/fittable/samples/package.js | 9 - lib/layout/fittable/samples/sample.css | 76 - lib/layout/fittable/source/FittableColumns.js | 19 - lib/layout/fittable/source/FittableLayout.css | 69 - lib/layout/fittable/source/FittableLayout.js | 156 - lib/layout/fittable/source/FittableRows.js | 17 - lib/layout/fittable/source/package.js | 6 - lib/layout/imageview/package.js | 3 - .../imageview/samples/ImageCarouselSample.css | 8 - .../samples/ImageCarouselSample.html | 22 - .../imageview/samples/ImageCarouselSample.js | 74 - .../imageview/samples/ImageViewSample.css | 0 .../imageview/samples/ImageViewSample.html | 22 - .../imageview/samples/ImageViewSample.js | 28 - lib/layout/imageview/samples/assets/earth.jpg | Bin 157230 -> 0 bytes .../imageview/samples/assets/favicon.ico | Bin 1150 -> 0 bytes lib/layout/imageview/samples/assets/globe.jpg | Bin 280339 -> 0 bytes .../imageview/samples/assets/jupiter.jpg | Bin 27149 -> 0 bytes lib/layout/imageview/samples/assets/mars.jpg | Bin 116236 -> 0 bytes .../imageview/samples/assets/mercury.jpg | Bin 206369 -> 0 bytes .../imageview/samples/assets/neptune.jpg | Bin 83489 -> 0 bytes lib/layout/imageview/samples/assets/pin.png | Bin 1341 -> 0 bytes .../imageview/samples/assets/saturn.jpg | Bin 75869 -> 0 bytes .../imageview/samples/assets/uranus.jpg | Bin 46984 -> 0 bytes lib/layout/imageview/samples/assets/venus.jpg | Bin 149675 -> 0 bytes lib/layout/imageview/samples/package.js | 6 - lib/layout/imageview/source/ImageCarousel.js | 208 - lib/layout/imageview/source/ImageView.js | 379 -- lib/layout/imageview/source/ImageViewPin.css | 5 - lib/layout/imageview/source/ImageViewPin.js | 123 - lib/layout/imageview/source/package.js | 6 - lib/layout/list/package.js | 3 - .../list/samples/FlyweightRepeaterSample.css | 16 - .../list/samples/FlyweightRepeaterSample.html | 23 - .../list/samples/FlyweightRepeaterSample.js | 59 - lib/layout/list/samples/ListAroundSample.css | 59 - lib/layout/list/samples/ListAroundSample.html | 23 - lib/layout/list/samples/ListAroundSample.js | 211 - lib/layout/list/samples/ListBasicSample.css | 28 - lib/layout/list/samples/ListBasicSample.html | 22 - lib/layout/list/samples/ListBasicSample.js | 27 - .../list/samples/ListContactsSample.css | 57 - .../list/samples/ListContactsSample.html | 23 - lib/layout/list/samples/ListContactsSample.js | 261 - .../list/samples/ListLanguagesSample.css | 64 - .../list/samples/ListLanguagesSample.html | 23 - .../list/samples/ListLanguagesSample.js | 160 - .../list/samples/ListNoSelectSample.html | 22 - lib/layout/list/samples/ListNoSelectSample.js | 26 - .../list/samples/ListOnyxItemSample.html | 23 - lib/layout/list/samples/ListOnyxItemSample.js | 39 - .../list/samples/ListPulldownSample.css | 15 - .../list/samples/ListPulldownSample.html | 22 - lib/layout/list/samples/ListPulldownSample.js | 97 - lib/layout/list/samples/NameGenerator.js | 48 - .../samples/PersistentSwipeableItemSample.css | 42 - .../PersistentSwipeableItemSample.html | 21 - .../samples/PersistentSwipeableItemSample.js | 60 - .../list/samples/assets/avatars/angel.png | Bin 2476 -> 0 bytes .../samples/assets/avatars/astrologer.png | Bin 2142 -> 0 bytes .../list/samples/assets/avatars/athlete.png | Bin 2070 -> 0 bytes .../list/samples/assets/avatars/baby.png | Bin 1756 -> 0 bytes .../list/samples/assets/avatars/clown.png | Bin 2247 -> 0 bytes .../list/samples/assets/avatars/devil.png | Bin 2236 -> 0 bytes .../list/samples/assets/avatars/doctor.png | Bin 2184 -> 0 bytes .../list/samples/assets/avatars/dude.png | Bin 2196 -> 0 bytes .../list/samples/assets/avatars/dude2.png | Bin 2236 -> 0 bytes .../list/samples/assets/avatars/dude3.png | Bin 2067 -> 0 bytes .../list/samples/assets/avatars/dude4.png | Bin 2154 -> 0 bytes .../list/samples/assets/avatars/dude5.png | Bin 2065 -> 0 bytes .../list/samples/assets/avatars/dude6.png | Bin 2063 -> 0 bytes lib/layout/list/samples/assets/bg.png | Bin 79561 -> 0 bytes .../list/samples/assets/item-hilite.png | Bin 541 -> 0 bytes lib/layout/list/samples/assets/pulldown.png | Bin 3031 -> 0 bytes lib/layout/list/samples/assets/pullup.png | Bin 3028 -> 0 bytes .../list/samples/assets/remove-icon.png | Bin 2631 -> 0 bytes .../samples/assets/search-input-search.png | Bin 447 -> 0 bytes lib/layout/list/samples/assets/spinner.gif | Bin 664 -> 0 bytes lib/layout/list/samples/package.js | 18 - lib/layout/list/source/AlphaJumpList.js | 37 - lib/layout/list/source/AlphaJumper.css | 36 - lib/layout/list/source/AlphaJumper.js | 70 - lib/layout/list/source/AroundList.js | 67 - lib/layout/list/source/FlyweightRepeater.js | 248 - lib/layout/list/source/List.css | 49 - lib/layout/list/source/List.js | 1502 ------ lib/layout/list/source/PulldownList.css | 60 - lib/layout/list/source/PulldownList.js | 202 - lib/layout/list/source/package.js | 8 - lib/layout/list/source/wip-package.js | 6 - lib/layout/package.js | 8 - lib/layout/panels/package.js | 3 - .../panels/samples/PanelsFlickrSample.css | 72 - .../panels/samples/PanelsFlickrSample.html | 23 - .../panels/samples/PanelsFlickrSample.js | 152 - lib/layout/panels/samples/PanelsSample.css | 40 - lib/layout/panels/samples/PanelsSample.html | 23 - lib/layout/panels/samples/PanelsSample.js | 108 - .../panels/samples/PanelsSlidingSample.css | 17 - .../panels/samples/PanelsSlidingSample.html | 23 - .../panels/samples/PanelsSlidingSample.js | 35 - .../samples/assets/search-input-search.png | Bin 447 -> 0 bytes .../panels/samples/assets/spinner-large.gif | Bin 1924 -> 0 bytes lib/layout/panels/samples/assets/spinner.gif | Bin 664 -> 0 bytes lib/layout/panels/samples/menutest.html | 59 - lib/layout/panels/samples/package.js | 8 - lib/layout/panels/source/Panels.css | 12 - lib/layout/panels/source/Panels.js | 427 -- .../panels/source/arrangers/Arranger.css | 25 - .../panels/source/arrangers/Arranger.js | 230 - .../panels/source/arrangers/CardArranger.js | 53 - .../source/arrangers/CardSlideInArranger.js | 67 - .../source/arrangers/CarouselArranger.js | 117 - .../source/arrangers/CollapsingArranger.js | 101 - .../source/arrangers/DockRightArranger.js | 133 - .../panels/source/arrangers/OtherArrangers.js | 258 - lib/layout/panels/source/arrangers/package.js | 10 - lib/layout/panels/source/package.js | 5 - lib/layout/slideable/package.js | 3 - .../slideable/samples/SlideableSample.css | 41 - .../slideable/samples/SlideableSample.html | 22 - .../slideable/samples/SlideableSample.js | 98 - lib/layout/slideable/samples/package.js | 4 - lib/layout/slideable/source/Slideable.js | 316 -- lib/layout/slideable/source/package.js | 3 - lib/layout/tree/package.js | 3 - lib/layout/tree/samples/TreeSample.css | 0 lib/layout/tree/samples/TreeSample.html | 22 - lib/layout/tree/samples/TreeSample.js | 43 - lib/layout/tree/samples/assets/file.png | Bin 609 -> 0 bytes .../tree/samples/assets/folder-open.png | Bin 817 -> 0 bytes lib/layout/tree/samples/assets/folder.png | Bin 808 -> 0 bytes lib/layout/tree/samples/package.js | 3 - lib/layout/tree/source/Node.css | 30 - lib/layout/tree/source/Node.js | 269 - lib/layout/tree/source/package.js | 4 - lib/onyx/CONTRIBUTING md | 44 - lib/onyx/LICENSE-2.0.txt | 202 - lib/onyx/README.md | 29 - lib/onyx/css/Button.less | 71 - lib/onyx/css/ButtonColors.less | 25 - lib/onyx/css/Checkbox.less | 20 - lib/onyx/css/ContextualPopup.less | 230 - lib/onyx/css/DatePicker.less | 14 - lib/onyx/css/Grabber.less | 7 - lib/onyx/css/Groupbox.less | 67 - lib/onyx/css/Icon.less | 21 - lib/onyx/css/Input.less | 45 - lib/onyx/css/Item.less | 24 - lib/onyx/css/Menu.less | 64 - lib/onyx/css/MoreToolbar.less | 30 - lib/onyx/css/Picker.less | 49 - lib/onyx/css/Popup.less | 14 - lib/onyx/css/ProgressBar.less | 69 - lib/onyx/css/ProgressButton.less | 33 - lib/onyx/css/RadioButton.less | 37 - lib/onyx/css/RangeSlider.less | 10 - lib/onyx/css/RichText.less | 26 - lib/onyx/css/Scrim.less | 23 - lib/onyx/css/Slider.less | 24 - lib/onyx/css/Spinner.less | 11 - lib/onyx/css/TabButton.less | 7 - lib/onyx/css/TextArea.less | 32 - lib/onyx/css/TimePicker.less | 12 - lib/onyx/css/ToggleButton.less | 65 - lib/onyx/css/Toolbar.less | 64 - lib/onyx/css/Tooltip.less | 70 - lib/onyx/css/onyx-rules.less | 78 - lib/onyx/css/onyx-variables.less | 140 - lib/onyx/css/onyx.css | 1153 ----- lib/onyx/css/onyx.less | 5 - lib/onyx/css/package.js | 3 - lib/onyx/deploy.bat | 32 - lib/onyx/deploy.sh | 19 - lib/onyx/design/inline-controlled.html | 231 - lib/onyx/design/inline.html | 103 - lib/onyx/design/menu-icon-bookmark.png | Bin 1883 -> 0 bytes lib/onyx/design/toolbar-extended.html | 243 - lib/onyx/design/toolbar.html | 111 - lib/onyx/images/checkbox.png | Bin 5462 -> 0 bytes lib/onyx/images/grabbutton.png | Bin 676 -> 0 bytes lib/onyx/images/gradient-invert.png | Bin 255 -> 0 bytes lib/onyx/images/gradient.png | Bin 255 -> 0 bytes lib/onyx/images/more.png | Bin 2696 -> 0 bytes lib/onyx/images/progress-button-cancel.png | Bin 2631 -> 0 bytes lib/onyx/images/search-input-cancel.png | Bin 303 -> 0 bytes lib/onyx/images/search-input-search.png | Bin 447 -> 0 bytes lib/onyx/images/slider-handle.png | Bin 3095 -> 0 bytes lib/onyx/images/spinner-dark.gif | Bin 1924 -> 0 bytes lib/onyx/images/spinner-light.gif | Bin 1924 -> 0 bytes lib/onyx/package.js | 4 - lib/onyx/samples/ButtonGroupSample.html | 22 - lib/onyx/samples/ButtonGroupSample.js | 45 - lib/onyx/samples/ButtonSample.html | 22 - lib/onyx/samples/ButtonSample.js | 46 - lib/onyx/samples/CheckboxSample.html | 22 - lib/onyx/samples/CheckboxSample.js | 34 - lib/onyx/samples/ContextualPopupSample.html | 23 - lib/onyx/samples/ContextualPopupSample.js | 240 - lib/onyx/samples/DatePickerSample.html | 23 - lib/onyx/samples/DatePickerSample.js | 108 - lib/onyx/samples/DrawerSample.css | 33 - lib/onyx/samples/DrawerSample.html | 22 - lib/onyx/samples/DrawerSample.js | 41 - lib/onyx/samples/GroupboxSample.html | 22 - lib/onyx/samples/GroupboxSample.js | 40 - lib/onyx/samples/IconButtonSample.html | 22 - lib/onyx/samples/IconButtonSample.js | 61 - lib/onyx/samples/InputSample.html | 22 - lib/onyx/samples/InputSample.js | 68 - lib/onyx/samples/MenuSample.html | 22 - lib/onyx/samples/MenuSample.js | 99 - lib/onyx/samples/MoreToolbarSample.html | 22 - lib/onyx/samples/MoreToolbarSample.js | 35 - lib/onyx/samples/PickerSample.html | 22 - lib/onyx/samples/PickerSample.js | 101 - lib/onyx/samples/PopupSample.html | 22 - lib/onyx/samples/PopupSample.js | 65 - lib/onyx/samples/ProgressSample.html | 22 - lib/onyx/samples/ProgressSample.js | 81 - lib/onyx/samples/SliderSample.html | 22 - lib/onyx/samples/SliderSample.js | 98 - lib/onyx/samples/SpinnerSample.html | 22 - lib/onyx/samples/SpinnerSample.js | 18 - lib/onyx/samples/TimePickerSample.html | 23 - lib/onyx/samples/TimePickerSample.js | 100 - lib/onyx/samples/ToggleButtonSample.html | 22 - lib/onyx/samples/ToggleButtonSample.js | 35 - lib/onyx/samples/ToolbarSample.html | 23 - lib/onyx/samples/ToolbarSample.js | 66 - lib/onyx/samples/TooltipSample.html | 22 - lib/onyx/samples/TooltipSample.js | 92 - lib/onyx/samples/assets/favicon.ico | Bin 1150 -> 0 bytes lib/onyx/samples/assets/fish_bowl.png | Bin 2632 -> 0 bytes .../samples/assets/menu-icon-bookmark.png | Bin 1883 -> 0 bytes .../samples/assets/search-input-search.png | Bin 447 -> 0 bytes lib/onyx/samples/package.js | 23 - lib/onyx/samples/sample.css | 43 - lib/onyx/source/Button.js | 38 - lib/onyx/source/Checkbox.js | 34 - lib/onyx/source/ContextualPopup.js | 514 -- lib/onyx/source/DatePicker.js | 205 - lib/onyx/source/Drawer.js | 115 - lib/onyx/source/FlyweightPicker.js | 131 - lib/onyx/source/Grabber.js | 19 - lib/onyx/source/Groupbox.js | 41 - lib/onyx/source/Icon.js | 37 - lib/onyx/source/IconButton.js | 54 - lib/onyx/source/Input.js | 19 - lib/onyx/source/InputDecorator.js | 61 - lib/onyx/source/IntegerPicker.js | 78 - lib/onyx/source/Item.js | 42 - lib/onyx/source/Menu.js | 193 - lib/onyx/source/MenuDecorator.js | 62 - lib/onyx/source/MenuItem.js | 66 - lib/onyx/source/MoreToolbar.js | 156 - lib/onyx/source/Picker.js | 103 - lib/onyx/source/PickerButton.js | 22 - lib/onyx/source/PickerDecorator.js | 30 - lib/onyx/source/Popup.js | 93 - lib/onyx/source/ProgressBar.js | 104 - lib/onyx/source/ProgressButton.js | 33 - lib/onyx/source/RadioButton.js | 13 - lib/onyx/source/RadioGroup.js | 20 - lib/onyx/source/RangeSlider.js | 227 - lib/onyx/source/RichText.js | 19 - lib/onyx/source/Scrim.js | 114 - lib/onyx/source/Slider.js | 136 - lib/onyx/source/Spinner.js | 31 - lib/onyx/source/TabPanels.js | 128 - lib/onyx/source/TextArea.js | 19 - lib/onyx/source/TimePicker.js | 210 - lib/onyx/source/ToggleButton.js | 118 - lib/onyx/source/ToggleIconButton.js | 58 - lib/onyx/source/Toolbar.js | 31 - lib/onyx/source/Tooltip.js | 86 - lib/onyx/source/TooltipDecorator.js | 45 - lib/onyx/source/design.js | 168 - lib/onyx/source/package.js | 42 - lib/onyx/source/wip-package.js | 3 - package.js | 11 +- source/Scheduler.css | 94 - source/Scheduler.js | 55 - source/Theme.less | 26 - source/function/calendar.css | 73 - source/function/calendar.js | 416 -- source/function/package.js | 8 - source/function/to_do.css | 16 - source/function/to_do.js | 114 - source/function/weekly.css | 93 - source/function/weekly.js | 526 -- source/package.js | 8 - tools/deploy.bat | 37 - tools/deploy.sh | 39 - 858 files changed, 178 insertions(+), 130993 deletions(-) delete mode 100644 README-CORDOVA-WEBOS.md delete mode 100644 api/assets/busy.gif delete mode 100644 api/assets/favicon.ico delete mode 100644 api/assets/manifest.json delete mode 100644 api/assets/search-input-search.png delete mode 100644 api/build/app.css delete mode 100644 api/build/app.js delete mode 100644 api/build/enyo.css delete mode 100644 api/build/enyo.js delete mode 100644 api/icon.png delete mode 100644 api/index.html delete mode 100644 assets/Diary.png delete mode 100644 assets/check.png delete mode 100644 assets/delete_button.png delete mode 100644 assets/dot.png delete mode 100644 assets/favicon.ico delete mode 100644 assets/left_arrow.png delete mode 100644 assets/month.png delete mode 100644 assets/right_arrow.png delete mode 100644 assets/week.png delete mode 100644 build/app.css delete mode 100644 build/app.js delete mode 100644 build/enyo.css delete mode 100644 build/enyo.js delete mode 100644 debug.html delete mode 100644 deploy.md delete mode 100644 deploy/bootplate/assets/favicon.ico delete mode 100644 deploy/bootplate/build/app.css delete mode 100644 deploy/bootplate/build/app.js delete mode 100644 deploy/bootplate/build/enyo.css delete mode 100644 deploy/bootplate/build/enyo.js delete mode 100644 deploy/bootplate/icon.png delete mode 100644 deploy/bootplate/index.html delete mode 100644 deploy/bootplate/lib/onyx/LICENSE-2.0.txt delete mode 100644 deploy/bootplate/lib/onyx/images/checkbox.png delete mode 100644 deploy/bootplate/lib/onyx/images/grabbutton.png delete mode 100644 deploy/bootplate/lib/onyx/images/gradient-invert.png delete mode 100644 deploy/bootplate/lib/onyx/images/gradient.png delete mode 100644 deploy/bootplate/lib/onyx/images/more.png delete mode 100644 deploy/bootplate/lib/onyx/images/progress-button-cancel.png delete mode 100644 deploy/bootplate/lib/onyx/images/search-input-cancel.png delete mode 100644 deploy/bootplate/lib/onyx/images/search-input-search.png delete mode 100644 deploy/bootplate/lib/onyx/images/slider-handle.png delete mode 100644 deploy/bootplate/lib/onyx/images/spinner-dark.gif delete mode 100644 deploy/bootplate/lib/onyx/images/spinner-light.gif delete mode 100644 enyo/CONTRIBUTING md delete mode 100644 enyo/LICENSE-2.0.txt delete mode 100644 enyo/README.md delete mode 100644 enyo/enyo.js delete mode 100644 enyo/loader.js delete mode 100644 enyo/minify/minify.bat delete mode 100644 enyo/minify/minify.sh delete mode 100644 enyo/minify/package.js delete mode 100644 enyo/package.json delete mode 100644 enyo/samples/AjaxSample.css delete mode 100644 enyo/samples/AjaxSample.html delete mode 100644 enyo/samples/AjaxSample.js delete mode 100644 enyo/samples/GestureSample.css delete mode 100644 enyo/samples/GestureSample.html delete mode 100644 enyo/samples/GestureSample.js delete mode 100644 enyo/samples/JsonpSample.css delete mode 100644 enyo/samples/JsonpSample.html delete mode 100644 enyo/samples/JsonpSample.js delete mode 100644 enyo/samples/PlatformSample.css delete mode 100644 enyo/samples/PlatformSample.html delete mode 100644 enyo/samples/PlatformSample.js delete mode 100644 enyo/samples/Playground.css delete mode 100644 enyo/samples/Playground.html delete mode 100644 enyo/samples/Playground.js delete mode 100644 enyo/samples/RepeaterSample.css delete mode 100644 enyo/samples/RepeaterSample.html delete mode 100644 enyo/samples/RepeaterSample.js delete mode 100644 enyo/samples/ScrollerSample.css delete mode 100644 enyo/samples/ScrollerSample.html delete mode 100644 enyo/samples/ScrollerSample.js delete mode 100644 enyo/samples/WebServiceSample.css delete mode 100644 enyo/samples/WebServiceSample.html delete mode 100644 enyo/samples/WebServiceSample.js delete mode 100644 enyo/samples/assets/Sample1.js delete mode 100644 enyo/samples/assets/Sample2.js delete mode 100644 enyo/samples/assets/Sample3.js delete mode 100644 enyo/samples/assets/Sample4.js delete mode 100644 enyo/samples/package.js delete mode 100644 enyo/source/ajax/Ajax.js delete mode 100644 enyo/source/ajax/AjaxProperties.js delete mode 100644 enyo/source/ajax/Async.js delete mode 100644 enyo/source/ajax/Jsonp.js delete mode 100644 enyo/source/ajax/WebService.js delete mode 100644 enyo/source/ajax/cookie.js delete mode 100644 enyo/source/ajax/formdata.js delete mode 100644 enyo/source/ajax/json.js delete mode 100644 enyo/source/ajax/package.js delete mode 100644 enyo/source/ajax/xhr.js delete mode 100644 enyo/source/boot/boot.js delete mode 100644 enyo/source/boot/enyo.js delete mode 100644 enyo/source/boot/package.js delete mode 100644 enyo/source/dom/Control.js delete mode 100644 enyo/source/dom/animation.js delete mode 100644 enyo/source/dom/dispatcher.js delete mode 100644 enyo/source/dom/dom.css delete mode 100644 enyo/source/dom/dom.js delete mode 100644 enyo/source/dom/drag.js delete mode 100644 enyo/source/dom/gesture.js delete mode 100644 enyo/source/dom/modal.js delete mode 100644 enyo/source/dom/package.js delete mode 100644 enyo/source/dom/phonegap.js delete mode 100644 enyo/source/dom/platform.js delete mode 100644 enyo/source/dom/preview.js delete mode 100644 enyo/source/dom/transform.js delete mode 100644 enyo/source/dom/transition.js delete mode 100644 enyo/source/kernel/Component.js delete mode 100644 enyo/source/kernel/Layout.js delete mode 100644 enyo/source/kernel/Object.js delete mode 100644 enyo/source/kernel/Oop.js delete mode 100644 enyo/source/kernel/Signals.js delete mode 100644 enyo/source/kernel/UiComponent.js delete mode 100644 enyo/source/kernel/job.js delete mode 100644 enyo/source/kernel/lang.js delete mode 100644 enyo/source/kernel/log.js delete mode 100644 enyo/source/kernel/macroize.js delete mode 100644 enyo/source/kernel/package.js delete mode 100644 enyo/source/package.js delete mode 100644 enyo/source/touch/ScrollMath.js delete mode 100644 enyo/source/touch/ScrollStrategy.js delete mode 100644 enyo/source/touch/Scroller.css delete mode 100644 enyo/source/touch/Scroller.js delete mode 100644 enyo/source/touch/Thumb.css delete mode 100644 enyo/source/touch/Thumb.js delete mode 100644 enyo/source/touch/TouchScrollStrategy.js delete mode 100644 enyo/source/touch/TransitionScrollStrategy.js delete mode 100644 enyo/source/touch/TranslateScrollStrategy.js delete mode 100644 enyo/source/touch/gesture.js delete mode 100644 enyo/source/touch/msevents.js delete mode 100644 enyo/source/touch/package.js delete mode 100644 enyo/source/touch/touch.js delete mode 100644 enyo/source/ui/Animator.js delete mode 100644 enyo/source/ui/BaseLayout.js delete mode 100644 enyo/source/ui/Button.js delete mode 100644 enyo/source/ui/Checkbox.js delete mode 100644 enyo/source/ui/DragAvatar.js delete mode 100644 enyo/source/ui/FloatingLayer.js delete mode 100644 enyo/source/ui/Group.js delete mode 100644 enyo/source/ui/GroupItem.js delete mode 100644 enyo/source/ui/Image.js delete mode 100644 enyo/source/ui/Input.js delete mode 100644 enyo/source/ui/Popup.js delete mode 100644 enyo/source/ui/Repeater.js delete mode 100644 enyo/source/ui/RichText.js delete mode 100644 enyo/source/ui/Select.js delete mode 100644 enyo/source/ui/Selection.js delete mode 100644 enyo/source/ui/Table.js delete mode 100644 enyo/source/ui/TextArea.js delete mode 100644 enyo/source/ui/ToolDecorator.js delete mode 100644 enyo/source/ui/package.js delete mode 100644 enyo/source/ui/ui.css delete mode 100644 enyo/tools/README.md delete mode 100644 enyo/tools/deploy.js delete mode 100644 enyo/tools/lessc.bat delete mode 100644 enyo/tools/lessc.sh delete mode 100644 enyo/tools/minifier/lessc.js delete mode 100644 enyo/tools/minifier/minify.js delete mode 100644 enyo/tools/minifier/node_modules/less/CHANGELOG.md delete mode 100644 enyo/tools/minifier/node_modules/less/LICENSE delete mode 100644 enyo/tools/minifier/node_modules/less/Makefile delete mode 100644 enyo/tools/minifier/node_modules/less/README.md delete mode 100644 enyo/tools/minifier/node_modules/less/benchmark/benchmark.less delete mode 100644 enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js delete mode 100644 enyo/tools/minifier/node_modules/less/bin/lessc delete mode 100644 enyo/tools/minifier/node_modules/less/build/amd.js delete mode 100644 enyo/tools/minifier/node_modules/less/build/ecma-5.js delete mode 100644 enyo/tools/minifier/node_modules/less/build/header.js delete mode 100644 enyo/tools/minifier/node_modules/less/build/require-rhino.js delete mode 100644 enyo/tools/minifier/node_modules/less/build/require.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.1.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.2.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.3.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.4.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.5.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.6.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.0.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.1.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.2.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.3.js delete mode 100644 enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/browser.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/colors.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/cssmin.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/functions.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/index.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/parser.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/rhino.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/call.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/color.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/element.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/import.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/media.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/url.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/value.js delete mode 100644 enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js delete mode 100644 enyo/tools/minifier/node_modules/less/package.json delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/colors.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/comments.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/css-3.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/css-escapes.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/css.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/functions.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/ie-filters.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/import-once.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/import.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/javascript.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/media.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-args.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-important.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/mixins.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/operations.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/parens.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/rulesets.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/scope.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/selectors.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/strings.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/variables.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/css/whitespace.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/less-test.js delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/colors.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/comments.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/css-3.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/css-escapes.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/css.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/functions.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/ie-filters.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import-once.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/javascript.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/media.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-args.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-important.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/mixins.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/operations.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/parens.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/rulesets.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/scope.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/selectors.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/strings.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/variables.less delete mode 100644 enyo/tools/minifier/node_modules/less/test/less/whitespace.less delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/.npmignore delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/README.html delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/README.org delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/bin/uglifyjs delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/docstyle.css delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/consolidator.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/parse-js.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/process.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/lib/squeeze-more.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/package.json delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/beautify.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/testparser.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array1.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array2.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array3.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/array4.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/assignment.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/concatstring.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/const.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/forstatement.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/if.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue10.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue11.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue13.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue14.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue16.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue17.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue20.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue21.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue25.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue27.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue278.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue28.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue29.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue30.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue34.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue4.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue48.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue50.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue53.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue68.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue69.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue9.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/mangle.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/null_string.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/var.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/whitespace.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/expected/with.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array1.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array2.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array3.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/array4.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/assignment.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/concatstring.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/const.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/forstatement.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/if.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/ifreturn.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue10.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue11.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue13.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue14.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue16.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue17.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue20.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue21.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue25.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue27.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue278.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue28.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue29.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue30.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/tmp/test.js delete mode 100644 enyo/tools/minifier/node_modules/uglify-js/uglify-js.js delete mode 100644 enyo/tools/minifier/node_modules/walker.js delete mode 100644 enyo/tools/minifier/path-relative-shim.js delete mode 100644 enyo/tools/minify.bat delete mode 100644 enyo/tools/minify.sh delete mode 100644 enyo/tools/node_modules/.bin/nopt delete mode 100644 enyo/tools/node_modules/.bin/shjs delete mode 100644 enyo/tools/node_modules/nopt/.npmignore delete mode 100644 enyo/tools/node_modules/nopt/LICENSE delete mode 100644 enyo/tools/node_modules/nopt/README.md delete mode 100644 enyo/tools/node_modules/nopt/bin/nopt.js delete mode 100644 enyo/tools/node_modules/nopt/examples/my-program.js delete mode 100644 enyo/tools/node_modules/nopt/lib/nopt.js delete mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/README.md delete mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js delete mode 100644 enyo/tools/node_modules/nopt/node_modules/abbrev/package.json delete mode 100644 enyo/tools/node_modules/nopt/package.json delete mode 100644 enyo/tools/node_modules/shelljs/.documentup.json delete mode 100644 enyo/tools/node_modules/shelljs/.travis.yml delete mode 100644 enyo/tools/node_modules/shelljs/LICENSE delete mode 100644 enyo/tools/node_modules/shelljs/README.md delete mode 100644 enyo/tools/node_modules/shelljs/bin/shjs delete mode 100644 enyo/tools/node_modules/shelljs/global.js delete mode 100644 enyo/tools/node_modules/shelljs/make.js delete mode 100644 enyo/tools/node_modules/shelljs/package.json delete mode 100644 enyo/tools/node_modules/shelljs/scripts/docs.js delete mode 100644 enyo/tools/node_modules/shelljs/scripts/run-tests.js delete mode 100644 enyo/tools/node_modules/shelljs/shell.js delete mode 100644 enyo/tools/node_modules/shelljs/test/.npmignore delete mode 100644 enyo/tools/node_modules/shelljs/test/cat.js delete mode 100644 enyo/tools/node_modules/shelljs/test/cd.js delete mode 100644 enyo/tools/node_modules/shelljs/test/cp.js delete mode 100644 enyo/tools/node_modules/shelljs/test/echo.js delete mode 100644 enyo/tools/node_modules/shelljs/test/env.js delete mode 100644 enyo/tools/node_modules/shelljs/test/exec.js delete mode 100644 enyo/tools/node_modules/shelljs/test/find.js delete mode 100644 enyo/tools/node_modules/shelljs/test/grep.js delete mode 100644 enyo/tools/node_modules/shelljs/test/ls.js delete mode 100644 enyo/tools/node_modules/shelljs/test/mkdir.js delete mode 100644 enyo/tools/node_modules/shelljs/test/mv.js delete mode 100644 enyo/tools/node_modules/shelljs/test/pwd.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/a.txt delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/a delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/b delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/node_script.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/tmp/output delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file1.txt delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/file2.txt delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/.hidden delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/a delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/b delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file1 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file1.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file2 delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/file2.js delete mode 100644 enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped delete mode 100644 enyo/tools/node_modules/shelljs/test/rm.js delete mode 100644 enyo/tools/node_modules/shelljs/test/sed.js delete mode 100644 enyo/tools/node_modules/shelljs/test/silent.js delete mode 100644 enyo/tools/node_modules/shelljs/test/tempdir.js delete mode 100644 enyo/tools/node_modules/shelljs/test/test.js delete mode 100644 enyo/tools/node_modules/shelljs/test/to.js delete mode 100644 enyo/tools/node_modules/shelljs/test/which.js delete mode 100644 enyo/tools/test/ajax/index.html delete mode 100644 enyo/tools/test/ajax/package.js delete mode 100644 enyo/tools/test/ajax/php/redball.jpg delete mode 100644 enyo/tools/test/ajax/php/test1.php delete mode 100644 enyo/tools/test/ajax/php/test2.php delete mode 100644 enyo/tools/test/ajax/php/test3.php delete mode 100644 enyo/tools/test/ajax/php/test4.php delete mode 100644 enyo/tools/test/ajax/php/test5.php delete mode 100644 enyo/tools/test/ajax/php/test6.php delete mode 100644 enyo/tools/test/ajax/tests/AjaxTest.js delete mode 100644 enyo/tools/test/ajax/tests/JsonpTest.js delete mode 100644 enyo/tools/test/ajax/tests/WebServiceTest.js delete mode 100644 enyo/tools/test/ajax/tests/XhrTest.js delete mode 100644 enyo/tools/test/ajax/tests/package.js delete mode 100644 enyo/tools/test/core/index.html delete mode 100644 enyo/tools/test/core/test.css delete mode 100644 enyo/tools/test/core/test.js delete mode 100644 enyo/tools/test/core/tests/AjaxTest.js delete mode 100644 enyo/tools/test/core/tests/AsyncTest.js delete mode 100644 enyo/tools/test/core/tests/ComponentDispatchTest.js delete mode 100644 enyo/tools/test/core/tests/ComponentHandlersTest.js delete mode 100644 enyo/tools/test/core/tests/ComponentTest.js delete mode 100644 enyo/tools/test/core/tests/ControlPropsTest.js delete mode 100644 enyo/tools/test/core/tests/ControlTest.js delete mode 100644 enyo/tools/test/core/tests/DecodePackagePathTest.js delete mode 100644 enyo/tools/test/core/tests/JsonTest.js delete mode 100644 enyo/tools/test/core/tests/KindTest.js delete mode 100644 enyo/tools/test/core/tests/LoaderTest.js delete mode 100644 enyo/tools/test/core/tests/PathResolverTest.js delete mode 100644 enyo/tools/test/core/tests/ViewportPositioningTest.js delete mode 100644 enyo/tools/test/core/tests/langTest.js delete mode 100644 enyo/tools/test/core/tests/loader1.js delete mode 100644 enyo/tools/test/core/tests/loader2a.js delete mode 100644 enyo/tools/test/core/tests/loader2b.js delete mode 100644 enyo/tools/test/core/tests/package.js delete mode 100644 gallery_images/Saramean.scheduler.jpg delete mode 100644 icon.png delete mode 100644 lib/layout/CONTRIBUTING md delete mode 100644 lib/layout/README.md delete mode 100644 lib/layout/deploy.bat delete mode 100644 lib/layout/deploy.sh delete mode 100644 lib/layout/design.js delete mode 100644 lib/layout/fittable/package.js delete mode 100644 lib/layout/fittable/samples/FittableAppLayout1.html delete mode 100644 lib/layout/fittable/samples/FittableAppLayout1.js delete mode 100644 lib/layout/fittable/samples/FittableAppLayout2.html delete mode 100644 lib/layout/fittable/samples/FittableAppLayout2.js delete mode 100644 lib/layout/fittable/samples/FittableAppLayout3.html delete mode 100644 lib/layout/fittable/samples/FittableAppLayout3.js delete mode 100644 lib/layout/fittable/samples/FittableAppLayout4.html delete mode 100644 lib/layout/fittable/samples/FittableAppLayout4.js delete mode 100644 lib/layout/fittable/samples/FittableDescription.html delete mode 100644 lib/layout/fittable/samples/FittableDescription.js delete mode 100644 lib/layout/fittable/samples/FittableSample.html delete mode 100644 lib/layout/fittable/samples/FittableSample.js delete mode 100644 lib/layout/fittable/samples/FittableTests.html delete mode 100644 lib/layout/fittable/samples/FittableTests.js delete mode 100644 lib/layout/fittable/samples/package.js delete mode 100644 lib/layout/fittable/samples/sample.css delete mode 100644 lib/layout/fittable/source/FittableColumns.js delete mode 100644 lib/layout/fittable/source/FittableLayout.css delete mode 100644 lib/layout/fittable/source/FittableLayout.js delete mode 100644 lib/layout/fittable/source/FittableRows.js delete mode 100644 lib/layout/fittable/source/package.js delete mode 100644 lib/layout/imageview/package.js delete mode 100644 lib/layout/imageview/samples/ImageCarouselSample.css delete mode 100644 lib/layout/imageview/samples/ImageCarouselSample.html delete mode 100644 lib/layout/imageview/samples/ImageCarouselSample.js delete mode 100644 lib/layout/imageview/samples/ImageViewSample.css delete mode 100644 lib/layout/imageview/samples/ImageViewSample.html delete mode 100644 lib/layout/imageview/samples/ImageViewSample.js delete mode 100644 lib/layout/imageview/samples/assets/earth.jpg delete mode 100644 lib/layout/imageview/samples/assets/favicon.ico delete mode 100644 lib/layout/imageview/samples/assets/globe.jpg delete mode 100644 lib/layout/imageview/samples/assets/jupiter.jpg delete mode 100644 lib/layout/imageview/samples/assets/mars.jpg delete mode 100644 lib/layout/imageview/samples/assets/mercury.jpg delete mode 100644 lib/layout/imageview/samples/assets/neptune.jpg delete mode 100644 lib/layout/imageview/samples/assets/pin.png delete mode 100644 lib/layout/imageview/samples/assets/saturn.jpg delete mode 100644 lib/layout/imageview/samples/assets/uranus.jpg delete mode 100644 lib/layout/imageview/samples/assets/venus.jpg delete mode 100644 lib/layout/imageview/samples/package.js delete mode 100644 lib/layout/imageview/source/ImageCarousel.js delete mode 100644 lib/layout/imageview/source/ImageView.js delete mode 100644 lib/layout/imageview/source/ImageViewPin.css delete mode 100644 lib/layout/imageview/source/ImageViewPin.js delete mode 100644 lib/layout/imageview/source/package.js delete mode 100644 lib/layout/list/package.js delete mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.css delete mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.html delete mode 100644 lib/layout/list/samples/FlyweightRepeaterSample.js delete mode 100644 lib/layout/list/samples/ListAroundSample.css delete mode 100644 lib/layout/list/samples/ListAroundSample.html delete mode 100644 lib/layout/list/samples/ListAroundSample.js delete mode 100644 lib/layout/list/samples/ListBasicSample.css delete mode 100644 lib/layout/list/samples/ListBasicSample.html delete mode 100644 lib/layout/list/samples/ListBasicSample.js delete mode 100644 lib/layout/list/samples/ListContactsSample.css delete mode 100644 lib/layout/list/samples/ListContactsSample.html delete mode 100644 lib/layout/list/samples/ListContactsSample.js delete mode 100644 lib/layout/list/samples/ListLanguagesSample.css delete mode 100644 lib/layout/list/samples/ListLanguagesSample.html delete mode 100644 lib/layout/list/samples/ListLanguagesSample.js delete mode 100644 lib/layout/list/samples/ListNoSelectSample.html delete mode 100644 lib/layout/list/samples/ListNoSelectSample.js delete mode 100644 lib/layout/list/samples/ListOnyxItemSample.html delete mode 100644 lib/layout/list/samples/ListOnyxItemSample.js delete mode 100644 lib/layout/list/samples/ListPulldownSample.css delete mode 100644 lib/layout/list/samples/ListPulldownSample.html delete mode 100644 lib/layout/list/samples/ListPulldownSample.js delete mode 100644 lib/layout/list/samples/NameGenerator.js delete mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.css delete mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.html delete mode 100644 lib/layout/list/samples/PersistentSwipeableItemSample.js delete mode 100644 lib/layout/list/samples/assets/avatars/angel.png delete mode 100644 lib/layout/list/samples/assets/avatars/astrologer.png delete mode 100644 lib/layout/list/samples/assets/avatars/athlete.png delete mode 100644 lib/layout/list/samples/assets/avatars/baby.png delete mode 100644 lib/layout/list/samples/assets/avatars/clown.png delete mode 100644 lib/layout/list/samples/assets/avatars/devil.png delete mode 100644 lib/layout/list/samples/assets/avatars/doctor.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude2.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude3.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude4.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude5.png delete mode 100644 lib/layout/list/samples/assets/avatars/dude6.png delete mode 100644 lib/layout/list/samples/assets/bg.png delete mode 100644 lib/layout/list/samples/assets/item-hilite.png delete mode 100644 lib/layout/list/samples/assets/pulldown.png delete mode 100644 lib/layout/list/samples/assets/pullup.png delete mode 100644 lib/layout/list/samples/assets/remove-icon.png delete mode 100644 lib/layout/list/samples/assets/search-input-search.png delete mode 100644 lib/layout/list/samples/assets/spinner.gif delete mode 100644 lib/layout/list/samples/package.js delete mode 100644 lib/layout/list/source/AlphaJumpList.js delete mode 100644 lib/layout/list/source/AlphaJumper.css delete mode 100644 lib/layout/list/source/AlphaJumper.js delete mode 100644 lib/layout/list/source/AroundList.js delete mode 100644 lib/layout/list/source/FlyweightRepeater.js delete mode 100644 lib/layout/list/source/List.css delete mode 100644 lib/layout/list/source/List.js delete mode 100644 lib/layout/list/source/PulldownList.css delete mode 100644 lib/layout/list/source/PulldownList.js delete mode 100644 lib/layout/list/source/package.js delete mode 100644 lib/layout/list/source/wip-package.js delete mode 100644 lib/layout/package.js delete mode 100644 lib/layout/panels/package.js delete mode 100644 lib/layout/panels/samples/PanelsFlickrSample.css delete mode 100644 lib/layout/panels/samples/PanelsFlickrSample.html delete mode 100644 lib/layout/panels/samples/PanelsFlickrSample.js delete mode 100644 lib/layout/panels/samples/PanelsSample.css delete mode 100644 lib/layout/panels/samples/PanelsSample.html delete mode 100644 lib/layout/panels/samples/PanelsSample.js delete mode 100644 lib/layout/panels/samples/PanelsSlidingSample.css delete mode 100644 lib/layout/panels/samples/PanelsSlidingSample.html delete mode 100644 lib/layout/panels/samples/PanelsSlidingSample.js delete mode 100644 lib/layout/panels/samples/assets/search-input-search.png delete mode 100644 lib/layout/panels/samples/assets/spinner-large.gif delete mode 100644 lib/layout/panels/samples/assets/spinner.gif delete mode 100644 lib/layout/panels/samples/menutest.html delete mode 100644 lib/layout/panels/samples/package.js delete mode 100644 lib/layout/panels/source/Panels.css delete mode 100644 lib/layout/panels/source/Panels.js delete mode 100644 lib/layout/panels/source/arrangers/Arranger.css delete mode 100644 lib/layout/panels/source/arrangers/Arranger.js delete mode 100644 lib/layout/panels/source/arrangers/CardArranger.js delete mode 100644 lib/layout/panels/source/arrangers/CardSlideInArranger.js delete mode 100644 lib/layout/panels/source/arrangers/CarouselArranger.js delete mode 100644 lib/layout/panels/source/arrangers/CollapsingArranger.js delete mode 100644 lib/layout/panels/source/arrangers/DockRightArranger.js delete mode 100644 lib/layout/panels/source/arrangers/OtherArrangers.js delete mode 100644 lib/layout/panels/source/arrangers/package.js delete mode 100644 lib/layout/panels/source/package.js delete mode 100644 lib/layout/slideable/package.js delete mode 100644 lib/layout/slideable/samples/SlideableSample.css delete mode 100644 lib/layout/slideable/samples/SlideableSample.html delete mode 100644 lib/layout/slideable/samples/SlideableSample.js delete mode 100644 lib/layout/slideable/samples/package.js delete mode 100644 lib/layout/slideable/source/Slideable.js delete mode 100644 lib/layout/slideable/source/package.js delete mode 100644 lib/layout/tree/package.js delete mode 100644 lib/layout/tree/samples/TreeSample.css delete mode 100644 lib/layout/tree/samples/TreeSample.html delete mode 100644 lib/layout/tree/samples/TreeSample.js delete mode 100644 lib/layout/tree/samples/assets/file.png delete mode 100644 lib/layout/tree/samples/assets/folder-open.png delete mode 100644 lib/layout/tree/samples/assets/folder.png delete mode 100644 lib/layout/tree/samples/package.js delete mode 100644 lib/layout/tree/source/Node.css delete mode 100644 lib/layout/tree/source/Node.js delete mode 100644 lib/layout/tree/source/package.js delete mode 100644 lib/onyx/CONTRIBUTING md delete mode 100644 lib/onyx/LICENSE-2.0.txt delete mode 100644 lib/onyx/README.md delete mode 100644 lib/onyx/css/Button.less delete mode 100644 lib/onyx/css/ButtonColors.less delete mode 100644 lib/onyx/css/Checkbox.less delete mode 100644 lib/onyx/css/ContextualPopup.less delete mode 100644 lib/onyx/css/DatePicker.less delete mode 100644 lib/onyx/css/Grabber.less delete mode 100644 lib/onyx/css/Groupbox.less delete mode 100644 lib/onyx/css/Icon.less delete mode 100644 lib/onyx/css/Input.less delete mode 100644 lib/onyx/css/Item.less delete mode 100644 lib/onyx/css/Menu.less delete mode 100644 lib/onyx/css/MoreToolbar.less delete mode 100644 lib/onyx/css/Picker.less delete mode 100644 lib/onyx/css/Popup.less delete mode 100644 lib/onyx/css/ProgressBar.less delete mode 100644 lib/onyx/css/ProgressButton.less delete mode 100644 lib/onyx/css/RadioButton.less delete mode 100644 lib/onyx/css/RangeSlider.less delete mode 100644 lib/onyx/css/RichText.less delete mode 100644 lib/onyx/css/Scrim.less delete mode 100644 lib/onyx/css/Slider.less delete mode 100644 lib/onyx/css/Spinner.less delete mode 100644 lib/onyx/css/TabButton.less delete mode 100644 lib/onyx/css/TextArea.less delete mode 100644 lib/onyx/css/TimePicker.less delete mode 100644 lib/onyx/css/ToggleButton.less delete mode 100644 lib/onyx/css/Toolbar.less delete mode 100644 lib/onyx/css/Tooltip.less delete mode 100644 lib/onyx/css/onyx-rules.less delete mode 100644 lib/onyx/css/onyx-variables.less delete mode 100644 lib/onyx/css/onyx.css delete mode 100644 lib/onyx/css/onyx.less delete mode 100644 lib/onyx/css/package.js delete mode 100644 lib/onyx/deploy.bat delete mode 100644 lib/onyx/deploy.sh delete mode 100644 lib/onyx/design/inline-controlled.html delete mode 100644 lib/onyx/design/inline.html delete mode 100644 lib/onyx/design/menu-icon-bookmark.png delete mode 100644 lib/onyx/design/toolbar-extended.html delete mode 100644 lib/onyx/design/toolbar.html delete mode 100644 lib/onyx/images/checkbox.png delete mode 100644 lib/onyx/images/grabbutton.png delete mode 100644 lib/onyx/images/gradient-invert.png delete mode 100644 lib/onyx/images/gradient.png delete mode 100644 lib/onyx/images/more.png delete mode 100644 lib/onyx/images/progress-button-cancel.png delete mode 100644 lib/onyx/images/search-input-cancel.png delete mode 100644 lib/onyx/images/search-input-search.png delete mode 100644 lib/onyx/images/slider-handle.png delete mode 100644 lib/onyx/images/spinner-dark.gif delete mode 100644 lib/onyx/images/spinner-light.gif delete mode 100644 lib/onyx/package.js delete mode 100644 lib/onyx/samples/ButtonGroupSample.html delete mode 100644 lib/onyx/samples/ButtonGroupSample.js delete mode 100644 lib/onyx/samples/ButtonSample.html delete mode 100644 lib/onyx/samples/ButtonSample.js delete mode 100644 lib/onyx/samples/CheckboxSample.html delete mode 100644 lib/onyx/samples/CheckboxSample.js delete mode 100644 lib/onyx/samples/ContextualPopupSample.html delete mode 100644 lib/onyx/samples/ContextualPopupSample.js delete mode 100644 lib/onyx/samples/DatePickerSample.html delete mode 100644 lib/onyx/samples/DatePickerSample.js delete mode 100644 lib/onyx/samples/DrawerSample.css delete mode 100644 lib/onyx/samples/DrawerSample.html delete mode 100644 lib/onyx/samples/DrawerSample.js delete mode 100644 lib/onyx/samples/GroupboxSample.html delete mode 100644 lib/onyx/samples/GroupboxSample.js delete mode 100644 lib/onyx/samples/IconButtonSample.html delete mode 100644 lib/onyx/samples/IconButtonSample.js delete mode 100644 lib/onyx/samples/InputSample.html delete mode 100644 lib/onyx/samples/InputSample.js delete mode 100644 lib/onyx/samples/MenuSample.html delete mode 100644 lib/onyx/samples/MenuSample.js delete mode 100644 lib/onyx/samples/MoreToolbarSample.html delete mode 100644 lib/onyx/samples/MoreToolbarSample.js delete mode 100644 lib/onyx/samples/PickerSample.html delete mode 100644 lib/onyx/samples/PickerSample.js delete mode 100644 lib/onyx/samples/PopupSample.html delete mode 100644 lib/onyx/samples/PopupSample.js delete mode 100644 lib/onyx/samples/ProgressSample.html delete mode 100644 lib/onyx/samples/ProgressSample.js delete mode 100644 lib/onyx/samples/SliderSample.html delete mode 100644 lib/onyx/samples/SliderSample.js delete mode 100644 lib/onyx/samples/SpinnerSample.html delete mode 100644 lib/onyx/samples/SpinnerSample.js delete mode 100644 lib/onyx/samples/TimePickerSample.html delete mode 100644 lib/onyx/samples/TimePickerSample.js delete mode 100644 lib/onyx/samples/ToggleButtonSample.html delete mode 100644 lib/onyx/samples/ToggleButtonSample.js delete mode 100644 lib/onyx/samples/ToolbarSample.html delete mode 100644 lib/onyx/samples/ToolbarSample.js delete mode 100644 lib/onyx/samples/TooltipSample.html delete mode 100644 lib/onyx/samples/TooltipSample.js delete mode 100644 lib/onyx/samples/assets/favicon.ico delete mode 100644 lib/onyx/samples/assets/fish_bowl.png delete mode 100644 lib/onyx/samples/assets/menu-icon-bookmark.png delete mode 100644 lib/onyx/samples/assets/search-input-search.png delete mode 100644 lib/onyx/samples/package.js delete mode 100644 lib/onyx/samples/sample.css delete mode 100644 lib/onyx/source/Button.js delete mode 100644 lib/onyx/source/Checkbox.js delete mode 100644 lib/onyx/source/ContextualPopup.js delete mode 100644 lib/onyx/source/DatePicker.js delete mode 100644 lib/onyx/source/Drawer.js delete mode 100644 lib/onyx/source/FlyweightPicker.js delete mode 100644 lib/onyx/source/Grabber.js delete mode 100644 lib/onyx/source/Groupbox.js delete mode 100644 lib/onyx/source/Icon.js delete mode 100644 lib/onyx/source/IconButton.js delete mode 100644 lib/onyx/source/Input.js delete mode 100644 lib/onyx/source/InputDecorator.js delete mode 100644 lib/onyx/source/IntegerPicker.js delete mode 100644 lib/onyx/source/Item.js delete mode 100644 lib/onyx/source/Menu.js delete mode 100644 lib/onyx/source/MenuDecorator.js delete mode 100644 lib/onyx/source/MenuItem.js delete mode 100644 lib/onyx/source/MoreToolbar.js delete mode 100644 lib/onyx/source/Picker.js delete mode 100644 lib/onyx/source/PickerButton.js delete mode 100644 lib/onyx/source/PickerDecorator.js delete mode 100644 lib/onyx/source/Popup.js delete mode 100644 lib/onyx/source/ProgressBar.js delete mode 100644 lib/onyx/source/ProgressButton.js delete mode 100644 lib/onyx/source/RadioButton.js delete mode 100644 lib/onyx/source/RadioGroup.js delete mode 100644 lib/onyx/source/RangeSlider.js delete mode 100644 lib/onyx/source/RichText.js delete mode 100644 lib/onyx/source/Scrim.js delete mode 100644 lib/onyx/source/Slider.js delete mode 100644 lib/onyx/source/Spinner.js delete mode 100644 lib/onyx/source/TabPanels.js delete mode 100644 lib/onyx/source/TextArea.js delete mode 100644 lib/onyx/source/TimePicker.js delete mode 100644 lib/onyx/source/ToggleButton.js delete mode 100644 lib/onyx/source/ToggleIconButton.js delete mode 100644 lib/onyx/source/Toolbar.js delete mode 100644 lib/onyx/source/Tooltip.js delete mode 100644 lib/onyx/source/TooltipDecorator.js delete mode 100644 lib/onyx/source/design.js delete mode 100644 lib/onyx/source/package.js delete mode 100644 lib/onyx/source/wip-package.js delete mode 100644 source/Scheduler.css delete mode 100644 source/Scheduler.js delete mode 100644 source/Theme.less delete mode 100644 source/function/calendar.css delete mode 100644 source/function/calendar.js delete mode 100644 source/function/package.js delete mode 100644 source/function/to_do.css delete mode 100644 source/function/to_do.js delete mode 100644 source/function/weekly.css delete mode 100644 source/function/weekly.js delete mode 100644 source/package.js delete mode 100644 tools/deploy.bat delete mode 100644 tools/deploy.sh diff --git a/README-CORDOVA-WEBOS.md b/README-CORDOVA-WEBOS.md deleted file mode 100644 index 8ecabdc..0000000 --- a/README-CORDOVA-WEBOS.md +++ /dev/null @@ -1,8 +0,0 @@ -Cordova webOS Instructions: ---------------------------- - -- Set up your project the same way you would set up any other bootplate project. -- Modify your index.html and JavaScript files as outlined in this blog post: [JavaScript Apps for Open webOS With Enyo and Cordova](http://blog.openwebosproject.org/post/39278618299/javascript-apps-for-open-webos-with-enyo-and-cordova) -- Copy appinfo.json from the PhoneGap 'lib/webos/framework' directory and a cordova JavaScript file from the PhoneGap 'lib/webos/lib' directory -- Modify appinfo.json for your project and add an icon -- run tools\deploy.bat --cordova-webos or tools/deploy.sh --cordova-webos to deploy your app. diff --git a/README.md b/README.md index ae66288..828a527 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,63 @@ -scheduler -========= +### About the Enyo Community Gallery ### -enyo scheduler application +We are really excited by the amount of collaboration and sharing happening in the [Enyo Forums](http://forums.enyojs.com/). This initial release of the [Enyo Community Gallery](http://enyojs.com/gallery) is a first step at providing a way to showcase and discover new Enyo add-on components and libraries developed by the community. There are many directions we can go with this, such as categorization and dependency management, but for now we wanted to get something barebones out quickly to capture all of the great work being produced by the community. + +Those interested in sharing their Enyo components, samples, etc. are encouraged to follow these instructions for getting their components showcased in the gallery. + +### Directions for Adding Components to Gallery ### + +The gallery is a simple Enyo app hosted from our github repo. To register a new component please follow these instructions: + +1. Fork the github repo (`git@github.com:enyojs/gallery.git`) +2. Edit the gallery_manifest.json file to add author and component info (see below) +3. If you want, add a line to the noscript part of index.html for your component. +4. Add a 200 x 200 px image/screenshot for your component to the gallery_images directory. + It should be JPEG and named with your component's unique component ID, e.g. `me.awesomecontrol.jpg`. +5. Commit your changes to your fork +6. Submit a github pull request to the `gh-pages` branch of `enyojs/gallery` + +The format of gallery_manifest.json is as follows: + + "owners": { // List of authors, referenced by component descriptions + "xxxx": { // Author id (github username) + "name": "", // Display name for author + "website": "", // Author's website + "twitter": "" // Author's twitter handle + }, + ... + } + "widgets": [ // The list of components in the gallery + { + "name": "", // Unique component id (owner.component) + "displayName": "", // Display name for component + "owner": "xxxx", // Author id, from above + "dependencies": [ // List of libraries this component requires + { + "name": "", // Name of dependency + "version": "" // Version of dependency + }, + ... + ], + "url": "", // URL to source code (i.e. github link) + "demoUrl": "", // URL to demo website (optional) + "submissionDate": "", // Date of submission (i.e. "Mar 26, 2012") + "testedPlatforms": "", // List of platforms this component was tested on + "license": "", // Reference to standard license (i.e. "Apache 2.0" or license text) + "version": "1", // Version of this component (optional) + "blurb": "" // Description of component + }, + ... + ] + + +Please note the following: + +* We will only accept pull requests to the catalog for OSS-licensed components from the original author. If you have forked another member's component please submit a separate, new component. +* There should be one unique "owner" entry per author. For the owner id please use your github username. You may choose your full name or username as the display name. +* The "website", "twitter", and "demoUrl" fields are optional and may be omitted if you wish. +* The "testedPlatforms" field should list the platforms you have tested your component on (i.e. "iOS 5.1", "Chrome 18", "IE9"). +* The "license" field should either reference a standard OSS license (i.e. "Apache 2.0") or include the text of your license. +* The "dependencies" field should list any other Enyo libraries your component requires (i.e. onyx, layout). +* The "version" field for dependencies is optional but will be displayed if present. +* You may include a "version" for your component, however we are not yet using this on the site. +* New entries in the index.html file should follow the format having a link to the gallery entry and the control name. diff --git a/api/assets/busy.gif b/api/assets/busy.gif deleted file mode 100644 index dba81f5113f127557dfdfad9ad5208bfd694c322..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 310 zcmZ?wbhEHbf=ZVnkn}S!FamXRfb`2GSO_27H%%Z}3|T)5P&Y_F z7fW06NtuTW1agq185!7NwzIS;CkZcfsalC-I12+zHxJMwD|QRAF)({oae<8I1pAa7 SVf&P{#ZrcQ86=8C7_0#!o;rsB diff --git a/api/assets/favicon.ico b/api/assets/favicon.ico deleted file mode 100644 index 52c86347fe3e10042c05374362757fa260307d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmb`FKMnyw7{#BEC=@o4NK}++2k<9R=-ogfBntOXlHdvyYK=~#aR8MgC>3JNvw6v6 zt=*BB&9}4j&HUcH{bqoSeS!e?UBfsBlmXOj*p$tLdE23F=SqbzI8JMq)4}u`6~jJl zZFFAje9-(^L+ot9~P>KuLiljZ#*X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/api/build/app.css b/api/build/app.css deleted file mode 100644 index 0e6a0bd..0000000 --- a/api/build/app.css +++ /dev/null @@ -1,889 +0,0 @@ - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/fittable/source/FittableLayout.css */ - -.enyo-fittable-rows-layout { - position: relative; -} - -.enyo-fittable-rows-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - /* float when not stretched */ - float: left; - clear: both; -} - -/* non-floating when stretched */ -.enyo-fittable-rows-layout.enyo-stretch > * { - float: none; - clear: none; -} - -/* setting to enforce margin collapsing */ -/* NOTE: rows cannot have margin left/right */ -.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { - float: left; - clear: both; - width: 100%; - /* note: harsh resets */ - margin-left: 0 !important; - margin-right: 0 !important; -} - -.enyo-fittable-columns-layout { - position: relative; - text-align: left; - white-space: nowrap; -} - -.enyo-fittable-columns-layout.enyo-center { - text-align: center; -} - -.enyo-fittable-columns-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - vertical-align: top; - display: inline-block; - white-space: normal; -} - -.enyo-fittable-columns-layout.enyo-tool-decorator > * { - vertical-align: middle; -} - -/* repair clobbered white-space setting for pre, code */ -.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { - white-space: pre; -} - -.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { - white-space: nowrap; -} - -/* NOTE: columns cannot have margin top/bottom */ -.enyo-fittable-columns-layout.enyo-stretch > * { - height: 100%; - /* note: harsh resets */ - margin-top: 0 !important; - margin-bottom: 0 !important; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/list/source/List.css */ - -.enyo-list { - position: relative; -} - -.enyo-list-port { - overflow: hidden; - position: relative; - height: 1000000px; -} - -.enyo-list-page, .enyo-list-holdingarea { - position: absolute; - left: 0; - right: 0; -} - -.enyo-list-holdingarea { - top: -10000px; -} - -.enyo-pinned-list-placeholder { - border: 1px solid red; - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-pinned-list-placeholder button { - width: 100px; height: 100%; - position: absolute; - top: 0; right: 0; -} - -.enyo-list-reorder-container { - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-animatedTopAndLeft { - -webkit-transition: top 0.1s linear, left 0.1s linear; - -moz-transition: top 0.1s linear, left 0.1s linear; - -o-transition: top 0.1s linear, left 0.1s linear; - transition: top 0.1s linear, left 0.1s linear; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/list/source/PulldownList.css */ - -.enyo-list-pulldown { - position: absolute; - bottom: 100%; - left: 0; - right: 0; -} - -.enyo-puller { - position: relative; - height: 50px; - font-size: 22px; - color: #444; - padding: 20px 0 0px 34px; -} - -.enyo-puller-text { - position: absolute; - left: 80px; - top: 22px; -} - -.enyo-puller-arrow { - position: relative; - background: #444; - width: 7px; - height: 28px; - transition: transform 0.3s; - -webkit-transition: -webkit-transform 0.3s; - -moz-transition: -moz-transform 0.3s; - -o-transition: -o-transform 0.3s; - -ms-transition: -ms-transform 0.3s; -} - -.enyo-puller-arrow:after { - content: " "; - height: 0; - width: 0; - position: absolute; - border: 10px solid transparent; - border-bottom-color: #444; - bottom: 100%; - left: 50%; - margin-left: -10px; -} - -.enyo-puller-arrow-up { - transform: rotate(0deg); - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -ms-transform: rotate(0deg); -} - -.enyo-puller-arrow-down { - transform: rotate(180deg); - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -o-transform: rotate(180deg); - -ms-transform: rotate(180deg); -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/panels/source/arrangers/Arranger.css */ - -.enyo-arranger { - position: relative; - overflow: hidden; -} - -.enyo-arranger.enyo-fit { - position: absolute; -} - -.enyo-arranger > * { - position: absolute; - left: 0; - top: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.enyo-arranger-fit > * { - /* override any width/height set on panels */ - width: 100% !important; - height: 100% !important; - min-width: 0 !important; - min-height: 0 !important; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/panels/source/Panels.css */ - -.enyo-panels { -} - -.enyo-panels-fit-narrow { -} - -@media all and (max-width: 800px) { - .enyo-panels-fit-narrow > * { - min-width: 100%; - max-width: 100%; - } -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/tree/source/Node.css */ - -.enyo-node { - cursor: default; - padding: 4px; -} - -.enyo-node img { - vertical-align: middle; - padding-right: 6px; -} - -.enyo-node-box { - overflow: hidden; -} - -.enyo-node-client { - position: relative; -} - -.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { - -ms-transition-property: height, top; - -ms-transition-duration: 0.2s, 0.2s; - -moz-transition-property: height, top; - -moz-transition-duration: 0.2s, 0.2s; - -o-transition-property: height, top; - -o-transition-duration: 0.2s, 0.2s; - -webkit-transition-property: height, top; - -webkit-transition-duration: 0.2s, 0.2s; - transition-property: height, top; - transition-duration: 0.2s, 0.2s; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/imageview/source/ImageViewPin.css */ - - -.pinDebug { - background:yellow; - border:1px solid yellow; -} - -/* ../source/foss/syntaxhighlighter_3.0.83_fork/sh-min.css */ - - -/* styles/shCoreEclipse.css */ - -/** - * SyntaxHighlighter - * http://alexgorbatchev.com/SyntaxHighlighter - * - * SyntaxHighlighter is donationware. If you are using it, please donate. - * http://alexgorbatchev.com/SyntaxHighlighter/donate.html - * - * @version - * 3.0.83 (July 02 2010) - * - * @copyright - * Copyright (C) 2004-2010 Alex Gorbatchev. - * - * @license - * Dual licensed under the MIT and GPL licenses. - */ -.syntaxhighlighter a, -.syntaxhighlighter div, -.syntaxhighlighter code, -.syntaxhighlighter table, -.syntaxhighlighter table td, -.syntaxhighlighter table tr, -.syntaxhighlighter table tbody, -.syntaxhighlighter table thead, -.syntaxhighlighter table caption, -.syntaxhighlighter textarea { - -moz-border-radius: 0 0 0 0 !important; - -webkit-border-radius: 0 0 0 0 !important; - background: none !important; - border: 0 !important; - bottom: auto !important; - float: none !important; - height: auto !important; - left: auto !important; - line-height: 1.1em !important; - margin: 0 !important; - outline: 0 !important; - overflow: visible !important; - padding: 0 !important; - position: static !important; - right: auto !important; - text-align: left !important; - top: auto !important; - vertical-align: baseline !important; - width: auto !important; - box-sizing: content-box !important; - font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; - font-weight: normal !important; - font-style: normal !important; - font-size: 1em !important; - min-height: inherit !important; - min-height: auto !important; -} - -.syntaxhighlighter { - width: 100% !important; - margin: 1em 0 1em 0 !important; - position: relative !important; - overflow: auto !important; - font-size: 1em !important; -} -.syntaxhighlighter.source { - overflow: hidden !important; -} -.syntaxhighlighter .bold { - font-weight: bold !important; -} -.syntaxhighlighter .italic { - font-style: italic !important; -} -.syntaxhighlighter .line { - white-space: pre !important; -} -.syntaxhighlighter table { - width: 100% !important; -} -.syntaxhighlighter table caption { - text-align: left !important; - padding: .5em 0 0.5em 1em !important; -} -.syntaxhighlighter table td.code { - width: 100% !important; -} -.syntaxhighlighter table td.code .container { - position: relative !important; -} -.syntaxhighlighter table td.code .container textarea { - box-sizing: border-box !important; - position: absolute !important; - left: 0 !important; - top: 0 !important; - width: 100% !important; - height: 100% !important; - border: none !important; - background: white !important; - padding-left: 1em !important; - overflow: hidden !important; - white-space: pre !important; -} -.syntaxhighlighter table td.gutter .line { - text-align: right !important; - padding: 0 0.5em 0 1em !important; -} -.syntaxhighlighter table td.code .line { - padding: 0 1em !important; -} -.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line { - padding-left: 0em !important; -} -.syntaxhighlighter.show { - display: block !important; -} -.syntaxhighlighter.collapsed table { - display: none !important; -} -.syntaxhighlighter.collapsed .toolbar { - padding: 0.1em 0.8em 0em 0.8em !important; - font-size: 1em !important; - position: static !important; - width: auto !important; - height: auto !important; -} -.syntaxhighlighter.collapsed .toolbar span { - display: inline !important; - margin-right: 1em !important; -} -.syntaxhighlighter.collapsed .toolbar span a { - padding: 0 !important; - display: none !important; -} -.syntaxhighlighter.collapsed .toolbar span a.expandSource { - display: inline !important; -} -.syntaxhighlighter .toolbar { - position: absolute !important; - right: 1px !important; - top: 1px !important; - width: 11px !important; - height: 11px !important; - font-size: 10px !important; - z-index: 10 !important; -} -.syntaxhighlighter .toolbar span.title { - display: inline !important; -} -.syntaxhighlighter .toolbar a { - display: block !important; - text-align: center !important; - text-decoration: none !important; - padding-top: 1px !important; -} -.syntaxhighlighter .toolbar a.expandSource { - display: none !important; -} -.syntaxhighlighter.ie { - font-size: .9em !important; - padding: 1px 0 1px 0 !important; -} -.syntaxhighlighter.ie .toolbar { - line-height: 8px !important; -} -.syntaxhighlighter.ie .toolbar a { - padding-top: 0px !important; -} -.syntaxhighlighter.printing .line.alt1 .content, -.syntaxhighlighter.printing .line.alt2 .content, -.syntaxhighlighter.printing .line.highlighted .number, -.syntaxhighlighter.printing .line.highlighted.alt1 .content, -.syntaxhighlighter.printing .line.highlighted.alt2 .content { - background: none !important; -} -.syntaxhighlighter.printing .line .number { - color: #bbbbbb !important; -} -.syntaxhighlighter.printing .line .content { - color: black !important; -} -.syntaxhighlighter.printing .toolbar { - display: none !important; -} -.syntaxhighlighter.printing a { - text-decoration: none !important; -} -.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a { - color: black !important; -} -.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a { - color: #008200 !important; -} -.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a { - color: blue !important; -} -.syntaxhighlighter.printing .keyword { - color: #006699 !important; - font-weight: bold !important; -} -.syntaxhighlighter.printing .preprocessor { - color: gray !important; -} -.syntaxhighlighter.printing .variable { - color: #aa7700 !important; -} -.syntaxhighlighter.printing .value { - color: #009900 !important; -} -.syntaxhighlighter.printing .functions { - color: #ff1493 !important; -} -.syntaxhighlighter.printing .constants { - color: #0066cc !important; -} -.syntaxhighlighter.printing .script { - font-weight: bold !important; -} -.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a { - color: gray !important; -} -.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a { - color: #ff1493 !important; -} -.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a { - color: red !important; -} -.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a { - color: black !important; -} - -.syntaxhighlighter { - background-color: white !important; -} -.syntaxhighlighter .line.alt1 { - background-color: white !important; -} -.syntaxhighlighter .line.alt2 { - background-color: white !important; -} -.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 { - background-color: #c3defe !important; -} -.syntaxhighlighter .line.highlighted.number { - color: white !important; -} -.syntaxhighlighter table caption { - color: black !important; -} -.syntaxhighlighter .gutter { - color: #787878 !important; -} -.syntaxhighlighter .gutter .line { - border-right: 3px solid #d4d0c8 !important; -} -.syntaxhighlighter .gutter .line.highlighted { - background-color: #d4d0c8 !important; - color: white !important; -} -.syntaxhighlighter.printing .line .content { - border: none !important; -} -.syntaxhighlighter.collapsed { - overflow: visible !important; -} -.syntaxhighlighter.collapsed .toolbar { - color: #3f5fbf !important; - background: white !important; - border: 1px solid #d4d0c8 !important; -} -.syntaxhighlighter.collapsed .toolbar a { - color: #3f5fbf !important; -} -.syntaxhighlighter.collapsed .toolbar a:hover { - color: #aa7700 !important; -} -.syntaxhighlighter .toolbar { - color: #a0a0a0 !important; - background: #d4d0c8 !important; - border: none !important; -} -.syntaxhighlighter .toolbar a { - color: #a0a0a0 !important; -} -.syntaxhighlighter .toolbar a:hover { - color: red !important; -} -.syntaxhighlighter .plain, .syntaxhighlighter .plain a { - color: black !important; -} -.syntaxhighlighter .comments, .syntaxhighlighter .comments a { - color: #3f5fbf !important; -} -.syntaxhighlighter .string, .syntaxhighlighter .string a { - color: #2a00ff !important; -} -.syntaxhighlighter .keyword { - color: #7f0055 !important; -} -.syntaxhighlighter .preprocessor { - color: #646464 !important; -} -.syntaxhighlighter .variable { - color: #aa7700 !important; -} -.syntaxhighlighter .value { - color: #009900 !important; -} -.syntaxhighlighter .functions { - color: #ff1493 !important; -} -.syntaxhighlighter .constants { - color: #0066cc !important; -} -.syntaxhighlighter .script { - font-weight: bold !important; - color: #7f0055 !important; - background-color: none !important; -} -.syntaxhighlighter .color1, .syntaxhighlighter .color1 a { - color: gray !important; -} -.syntaxhighlighter .color2, .syntaxhighlighter .color2 a { - color: #ff1493 !important; -} -.syntaxhighlighter .color3, .syntaxhighlighter .color3 a { - color: red !important; -} - -.syntaxhighlighter .keyword { - font-weight: bold !important; -} -.syntaxhighlighter .xml .keyword { - color: #3f7f7f !important; - font-weight: normal !important; -} -.syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a { - color: #7f007f !important; -} -.syntaxhighlighter .xml .string { - font-style: italic !important; - color: #2a00ff !important; -} - - -/* patch.css */ - -.syntaxhighlighter { - overflow: visible !important; -} - - - -/* ../source/App.css */ - -.tab { - background: whitesmoke; - border: 1px dotted silver; - padding: 6px; - margin: 0; -} - -.tab.active { - background: lightblue; -} - -.input-decorator { - padding: 6px 8px 10px 8px; - border-radius: 3px; - border: 1px solid; - border-color: rgba(0,0,0,0.1); - margin: 0; -} - -.input-decorator > input { - /* reset */ - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - font-size: 120%; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - /* -webkit-appearance: caret;*/ -} - -.packages-editor { - background: lightgrey; - padding: 20px; - border-radius: 8px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); -} - -#app_left { - width: 350px; - border: 1px solid orange; -} - -#app_left_tabs { - background: #eee; - font-size: 120%; -} - -#app_kinds { - padding: 8px; - font-size: 140%; -} - -#app_index { - padding: 8px; - font-size: 120%; -} - -#app_modules { - padding: 8px; - font-size: 140%; -} - -#app_packages { - padding: 8px; - font-size: 140%; -} - -#app_doc { - padding: 8px 8px; -} - -#app_scope { - padding: 8px; - border-bottom: 1px dotted silver; -} - -#app_header { - padding: 8px; -} - -#app_tocFrame { - white-space: nowrap; -} - -#app_toc { -} - -#app_bodyFrame { -} - -#app_body { - padding: 8px; -} - -/* ../source/presentation.css */ - -blockquote { - margin-top: 0; - margin-bottom: 0; -} - -blockquote hr { - border: 0; -} - -hr { - border-style: dotted; - border-bottom-style: none; - border-color: #ccc; -} - -a { - text-decoration: none; - border-bottom: 1px dotted lightblue; - color: #3B5982; - line-height: 1.3em; -} - -a:hover { - text-decoration: none; - text-shadow: 0 0 2px orange; - -webkit-transition: text-shadow 0.5s; - -moz-transition: text-shadow 0.5s; - -o-transition: text-shadow 0.5s; - -ms-transition: text-shadow 0.5s; -} - -/* -a { - text-decoration: none; - background-color: #ddd; - padding: 3px 8px; - border-radius: 12px; - line-height: 2em; - color: #333; -} - -a:hover { - background-color: lightblue; - -webkit-transition: background-color 0.5s; -} -*/ - -comment { - /*border-left: 2px dotted silver;*/ - background: whitesmoke; - display: block; - padding: 4px 0 4px 12px; - margin: 16px 0 4px; - /* - font-size: small; - padding: 8px; - font-style: italic; - color: green; - padding: 16px 0 8px; - */ -} - -label { - font-weight: bold; - color: #D38628; -} - -public { - color: Orange; - padding-right: 6px; - display: none; -} - -protected { - color: Red; - padding-right: 6px; -} - -published { - color: green; - padding-right: 6px; -} - -kind { - font-size: 130%; - font-weight: bold; - display: block; -} - -package { - color: black; - background-color: #B0E0E6; - font-size: 90%; - padding: 3pt; - float: right; -} - -moduleName { - font-size: 130%; - font-weight: bold; - display: block; -} - -superkind { - color: #555; - display: block; -} - -prototype { - font-style: italic; - /* - font-size: small; - color: blue; - */ - color: #888; -} - -module { - text-decoration: underline; - color: #C39; - cursor: pointer; -} - -topic { - /* - font-weight: bold; - text-decoration: underline; - color: #46E; - cursor: pointer; - */ -} - -column { - display: inline-block; - font-size: small; - padding: 16px; - /*border-right: 1px dotted silver;*/ - vertical-align: top; -} - -divider { - display: block; - color: #0D0D0D; - font-size: 120%; - font-weight: bold; - margin-left: -1px; - margin-top: 1em; - margin-bottom: 5px; - /*border-bottom: 1px dotted silver;*/ -} - -code { - background-color: white; - padding: 2px; -} - -arguments { - color: purple; -} - diff --git a/api/build/app.js b/api/build/app.js deleted file mode 100644 index 532b618..0000000 --- a/api/build/app.js +++ /dev/null @@ -1,4372 +0,0 @@ - -// minifier: path aliases - -enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/api-tool/enyo/tools/../../lib/layout/"}); - -// FittableLayout.js - -enyo.kind({ -name: "enyo.FittableLayout", -kind: "Layout", -calcFitIndex: function() { -for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; -}, -getFitControl: function() { -var e = this.container.children, t = e[this.fitIndex]; -return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; -}, -getLastControl: function() { -var e = this.container.children, t = e.length - 1, n = e[t]; -while ((n = e[t]) && !n.showing) t--; -return n; -}, -_reflow: function(e, t, n, r) { -this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); -var i = this.getFitControl(); -if (!i) return; -var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); -f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); -var l = i.getBounds(); -o = l[n] - (a && a[n] || 0); -var c = this.getLastControl(); -if (c) { -var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; -if (c != i) { -var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; -u = v - d; -} else u = h; -} -var m = s - (o + u); -i.applyStyle(e, m + "px"); -}, -reflow: function() { -this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); -} -}), enyo.kind({ -name: "enyo.FittableColumnsLayout", -kind: "FittableLayout", -orient: "h", -layoutClass: "enyo-fittable-columns-layout" -}), enyo.kind({ -name: "enyo.FittableRowsLayout", -kind: "FittableLayout", -layoutClass: "enyo-fittable-rows-layout", -orient: "v" -}); - -// FittableRows.js - -enyo.kind({ -name: "enyo.FittableRows", -layoutKind: "FittableRowsLayout", -noStretch: !1 -}); - -// FittableColumns.js - -enyo.kind({ -name: "enyo.FittableColumns", -layoutKind: "FittableColumnsLayout", -noStretch: !1 -}); - -// FlyweightRepeater.js - -enyo.kind({ -name: "enyo.FlyweightRepeater", -published: { -count: 0, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -clientClasses: "", -clientStyle: "", -rowOffset: 0 -}, -events: { -onSetupItem: "", -onRenderRow: "" -}, -bottomUp: !1, -components: [ { -kind: "Selection", -onSelect: "selectDeselect", -onDeselect: "selectDeselect" -}, { -name: "client" -} ], -create: function() { -this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); -}, -noSelectChanged: function() { -this.noSelect && this.$.selection.clear(); -}, -multiSelectChanged: function() { -this.$.selection.setMulti(this.multiSelect); -}, -clientClassesChanged: function() { -this.$.client.setClasses(this.clientClasses); -}, -clientStyleChanged: function() { -this.$.client.setStyle(this.clientStyle); -}, -setupItem: function(e) { -this.doSetupItem({ -index: e, -selected: this.isSelected(e) -}); -}, -generateChildHtml: function() { -var e = ""; -this.index = null; -for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); -return e; -}, -previewDomEvent: function(e) { -var t = this.index = this.rowForEvent(e); -e.rowIndex = e.index = t, e.flyweight = this; -}, -decorateEvent: function(e, t, n) { -var r = t && t.index != null ? t.index : this.index; -t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); -}, -tap: function(e, t) { -if (this.noSelect || t.index === -1) return; -this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); -}, -selectDeselect: function(e, t) { -this.renderRow(t.key); -}, -getSelection: function() { -return this.$.selection; -}, -isSelected: function(e) { -return this.getSelection().isSelected(e); -}, -renderRow: function(e) { -if (e < this.rowOffset || e >= this.count + this.rowOffset) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ -rowIndex: e -})); -}, -fetchRowNode: function(e) { -if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); -}, -rowForEvent: function(e) { -if (!this.hasNode()) return -1; -var t = e.target; -while (t && t !== this.node) { -var n = t.getAttribute && t.getAttribute("data-enyo-index"); -if (n !== null) return Number(n); -t = t.parentNode; -} -return -1; -}, -prepareRow: function(e) { -if (e < 0 || e >= this.count) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -enyo.FlyweightRepeater.claimNode(this.$.client, t); -}, -lockRow: function() { -this.$.client.teardownChildren(); -}, -performOnRow: function(e, t, n) { -if (e < 0 || e >= this.count) return; -t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); -}, -statics: { -claimNode: function(e, t) { -var n; -t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); -for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); -} -} -}); - -// List.js - -enyo.kind({ -name: "enyo.List", -kind: "Scroller", -classes: "enyo-list", -published: { -count: 0, -rowsPerPage: 50, -bottomUp: !1, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -fixedHeight: !1, -reorderable: !1, -centerReorderContainer: !0, -reorderComponents: [], -pinnedReorderComponents: [], -swipeableComponents: [], -enableSwipe: !1, -persistSwipeableItem: !1 -}, -events: { -onSetupItem: "", -onSetupReorderComponents: "", -onSetupPinnedReorderComponents: "", -onReorder: "", -onSetupSwipeItem: "", -onSwipeDrag: "", -onSwipe: "", -onSwipeComplete: "" -}, -handlers: { -onAnimateFinish: "animateFinish", -onRenderRow: "rowRendered", -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onup: "up", -onholdpulse: "holdpulse" -}, -rowHeight: 0, -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0;" -} ] -} ], -reorderHoldTimeMS: 600, -draggingRowIndex: -1, -draggingRowNode: null, -placeholderRowIndex: -1, -dragToScrollThreshold: .1, -prevScrollTop: 0, -autoScrollTimeoutMS: 20, -autoScrollTimeout: null, -autoscrollPageY: 0, -pinnedReorderMode: !1, -initialPinPosition: -1, -itemMoved: !1, -currentPageNumber: -1, -completeReorderTimeout: null, -swipeIndex: null, -swipeDirection: null, -persistentItemVisible: !1, -persistentItemOrigin: null, -swipeComplete: !1, -completeSwipeTimeout: null, -completeSwipeDelayMS: 500, -normalSwipeSpeedMS: 200, -fastSwipeSpeedMS: 100, -percentageDraggedThreshold: .2, -importProps: function(e) { -e && e.reorderable && (this.touch = !0), this.inherited(arguments); -}, -create: function() { -this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); -}, -initComponents: function() { -this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); -}, -createReorderTools: function() { -this.createComponent({ -name: "reorderContainer", -classes: "enyo-list-reorder-container", -ondown: "sendToStrategy", -ondrag: "sendToStrategy", -ondragstart: "sendToStrategy", -ondragfinish: "sendToStrategy", -onflick: "sendToStrategy" -}); -}, -createStrategy: function() { -this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); -}, -createSwipeableComponents: function() { -for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { -owner: this.owner -}); -}, -rendered: function() { -this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); -}, -resizeHandler: function() { -this.inherited(arguments), this.refresh(); -}, -bottomUpChanged: function() { -this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); -}, -noSelectChanged: function() { -this.$.generator.setNoSelect(this.noSelect); -}, -multiSelectChanged: function() { -this.$.generator.setMultiSelect(this.multiSelect); -}, -toggleSelectedChanged: function() { -this.$.generator.setToggleSelected(this.toggleSelected); -}, -countChanged: function() { -this.hasNode() && this.updateMetrics(); -}, -sendToStrategy: function(e, t) { -this.$.strategy.dispatchEvent("on" + t.type, t, e); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -holdpulse: function(e, t) { -if (!this.getReorderable() || this.isReordering()) return; -if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; -}, -dragstart: function(e, t) { -if (this.isReordering()) return !0; -if (this.isSwipeable()) return this.swipeDragStart(e, t); -}, -drag: function(e, t) { -if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; -if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; -}, -dragfinish: function(e, t) { -this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); -}, -up: function(e, t) { -this.isReordering() && this.finishReordering(e, t); -}, -generatePage: function(e, t) { -this.page = e; -var n = this.rowsPerPage * this.page; -this.$.generator.setRowOffset(n); -var r = Math.min(this.count - n, this.rowsPerPage); -this.$.generator.setCount(r); -var i = this.$.generator.generateChildHtml(); -t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); -var s = t.getBounds().height; -!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); -if (!this.fixedHeight) { -var o = this.getPageHeight(e); -this.pageHeights[e] = s, this.portSize += s - o; -} -}, -pageForRow: function(e) { -return Math.floor(e / this.rowsPerPage); -}, -preserveDraggingRowNode: function(e) { -this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); -}, -update: function(e) { -var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; -this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); -}, -getPageRowHeights: function(e) { -var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); -for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { -height: s.height, -width: s.width -}); -return t; -}, -updateRowBounds: function(e) { -this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); -}, -updateRowBoundsAtIndex: function(e, t, n) { -var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); -t[e].height = i.height, t[e].width = i.width; -}, -updateForPosition: function(e) { -this.update(this.calcPos(e)); -}, -calcPos: function(e) { -return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; -}, -adjustBottomPage: function() { -var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; -this.positionPage(e.pageNo, e); -}, -adjustPortSize: function() { -this.scrollerHeight = this.getBounds().height; -var e = Math.max(this.scrollerHeight, this.portSize); -this.$.port.applyStyle("height", e + "px"); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e); -t.applyStyle(this.pageBound, n + "px"); -}, -pageToPosition: function(e) { -var t = 0, n = e; -while (n > 0) n--, t += this.getPageHeight(n); -return t; -}, -positionToPageInfo: function(e) { -var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; -while (n >= 0) t++, r = this.getPageHeight(t), n -= r; -return t = Math.max(t, 0), { -no: t, -height: r, -pos: n + r, -startRow: t * this.rowsPerPage, -endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) -}; -}, -isPageInRange: function(e) { -return e == Math.max(0, Math.min(this.pageCount - 1, e)); -}, -getPageHeight: function(e) { -var t = this.pageHeights[e]; -if (!t) { -var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); -t = this.defaultPageHeight * (r / this.rowsPerPage); -} -return Math.max(1, t); -}, -invalidatePages: function() { -this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); -}, -invalidateMetrics: function() { -this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); -}, -scroll: function(e, t) { -var n = this.inherited(arguments), r = this.getScrollTop(); -return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); -}, -setScrollTop: function(e) { -this.update(e), this.inherited(arguments), this.twiddle(); -}, -getScrollPosition: function() { -return this.calcPos(this.getScrollTop()); -}, -setScrollPosition: function(e) { -this.setScrollTop(this.calcPos(e)); -}, -scrollToBottom: function() { -this.update(this.getScrollBounds().maxTop), this.inherited(arguments); -}, -scrollToRow: function(e) { -var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); -this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); -if (t == this.p0 || t == this.p1) { -var i = this.$.generator.fetchRowNode(e); -if (i) { -var s = i.offsetTop; -this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); -var o = this.getScrollPosition() + s; -this.setScrollPosition(o); -} -} -}, -scrollToStart: function() { -this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); -}, -scrollToEnd: function() { -this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); -}, -refresh: function() { -this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); -}, -reset: function() { -this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); -}, -getSelection: function() { -return this.$.generator.getSelection(); -}, -select: function(e, t) { -return this.getSelection().select(e, t); -}, -deselect: function(e) { -return this.getSelection().deselect(e); -}, -isSelected: function(e) { -return this.$.generator.isSelected(e); -}, -renderRow: function(e) { -this.$.generator.renderRow(e); -}, -rowRendered: function(e, t) { -this.updateRowBounds(t.rowIndex); -}, -prepareRow: function(e) { -this.$.generator.prepareRow(e); -}, -lockRow: function() { -this.$.generator.lockRow(); -}, -performOnRow: function(e, t, n) { -this.$.generator.performOnRow(e, t, n); -}, -animateFinish: function(e) { -return this.twiddle(), !0; -}, -twiddle: function() { -var e = this.getStrategy(); -enyo.call(e, "twiddle"); -}, -pageForPageNumber: function(e, t) { -return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; -}, -shouldStartReordering: function(e, t) { -return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; -}, -startReordering: function(e) { -this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); -}, -buildReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -styleReorderContainer: function(e) { -this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); -}, -appendNodeToReorderContainer: function(e) { -this.$.reorderContainer.createComponent({ -allowHtml: !0, -content: e.innerHTML -}).render(); -}, -centerReorderContainerOnPointer: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; -this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); -}, -positionReorderContainer: function(e, t) { -this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); -}, -setPositionReorderContainerTimeout: function() { -this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { -this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); -}), 100); -}, -clearPositionReorderContainerTimeout: function() { -this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); -}, -shouldDoReorderDrag: function() { -return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; -}, -reorderDrag: function(e) { -this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); -}, -updatePlaceholderPosition: function(e) { -var t = this.getRowIndexFromCoordinate(e); -t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); -}, -positionReorderNode: function(e) { -var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; -r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); -}, -checkForAutoScroll: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; -this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); -}, -stopAutoScrolling: function() { -this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); -}, -startAutoScrolling: function() { -this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); -}, -autoScroll: function() { -this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ -ddx: 0, -ddy: 0 -}), this.updatePlaceholderPosition(this.autoscrollPageY); -}, -movePlaceholderToIndex: function(e) { -var t, n; -if (e < 0) return; -e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); -var r = this.pageForRow(e); -r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; -}, -finishReordering: function(e, t) { -if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; -return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; -}, -moveReorderedContainerToDroppedPosition: function() { -var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); -this.positionReorderContainer(n, t); -}, -completeFinishReordering: function(e) { -this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); -if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { -this.beginPinnedReorder(e); -return; -} -this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); -}, -beginPinnedReorder: function(e) { -this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { -index: this.draggingRowIndex -})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; -}, -emptyAndHideReorderContainer: function() { -this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); -}, -buildPinnedReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -reorderRows: function(e) { -this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); -}, -makeReorderEvent: function(e) { -return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; -}, -positionReorderedNode: function() { -if (!this.removedInitialPage) { -var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); -e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; -if (this.currentPageNumber != this.initialPageNumber) { -var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); -this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); -} -} -}, -updateListIndices: function() { -if (this.shouldDoRefresh()) { -this.refresh(), this.correctPageHeights(); -return; -} -var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; -if (n === 1) { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); -for (i = t - 1, s = t; i >= e; i--) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); -} -r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); -} else { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); -for (i = e + 1, s = e; i <= t; i++) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); -} -} -}, -shouldDoRefresh: function() { -return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; -}, -getNodeStyle: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) return; -var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); -return { -h: r.height, -w: r.width, -left: n.left, -top: n.top -}; -}, -getRelativeOffset: function(e, t) { -var n = { -top: 0, -left: 0 -}; -if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); -return n; -}, -replaceNodeWithPlaceholder: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) { -enyo.log("No node - " + e); -return; -} -this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); -var n = this.pageForPageNumber(this.currentPageNumber); -n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); -}, -createPlaceholderNode: function(e) { -var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); -return t.style.height = n.height + "px", t.style.width = n.width + "px", t; -}, -removePlaceholderNode: function() { -this.removeNode(this.placeholderNode), this.placeholderNode = null; -}, -removeDraggingRowNode: function() { -this.draggingRowNode = null; -var e = this.$.holdingarea.hasNode(); -e.innerHTML = ""; -}, -removeNode: function(e) { -if (!e || !e.parentNode) return; -e.parentNode.removeChild(e); -}, -updatePageHeight: function(e) { -if (e < 0) return; -var t = this.pageForPageNumber(e, !0); -if (t) { -var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); -this.pageHeights[e] = r, this.portSize += r - n; -} -}, -updatePagePositions: function(e) { -this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); -}, -correctPageHeights: function() { -this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); -}, -hideNode: function(e) { -return e.style.display = "none", e; -}, -showNode: function(e) { -return e.style.display = "block", e; -}, -dropPinnedRow: function(e) { -this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); -return; -}, -cancelPinnedMode: function(e) { -this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); -}, -getRowIndexFromCoordinate: function(e) { -var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; -if (t < 0) return -1; -var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; -if (!r) return this.count; -var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; -for (var u = n.startRow; u <= n.endRow; ++u) { -if (u === this.placeholderRowIndex) { -o += s; -if (o >= i) return -1; -} -if (u !== this.draggingRowIndex) { -o += r[u].height; -if (o >= i) return u; -} -} -return u; -}, -getIndexPosition: function(e) { -return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); -}, -setItemPosition: function(e, t) { -var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; -e.addStyles(i); -}, -setItemBounds: function(e, t) { -var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; -e.addStyles(r); -}, -reorderScroll: function(e, t) { -this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); -}, -hideReorderingRow: function() { -var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); -e && (this.hiddenNode = this.hideNode(e)); -}, -isReordering: function() { -return this.draggingRowIndex > -1; -}, -isSwiping: function() { -return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; -}, -swipeDragStart: function(e, t) { -return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); -}, -swipeDrag: function(e, t) { -return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; -}, -swipeDragFinish: function(e, t) { -if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { -if (!this.isSwiping()) return !1; -var n = this.calcPercentageDragged(this.draggedXDistance); -n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); -} -return this.preventDragPropagation; -}, -isSwipeable: function() { -return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; -}, -positionSwipeableContainer: function(e, t) { -var n = this.$.generator.fetchRowNode(e); -if (!n) return; -var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; -this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); -}, -calcNewDragPosition: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; -return s; -}, -dragSwipeableComponents: function(e) { -this.$.swipeableComponents.applyStyle("left", e + "px"); -}, -startSwipe: function(e) { -e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); -}, -dragPersistentItem: function(e) { -var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); -this.$.swipeableComponents.applyStyle("left", n + "px"); -}, -dragFinishPersistentItem: function(e) { -var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; -this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); -}, -setPersistentItemOrigin: function(e) { -this.persistentItemOrigin = e == 1 ? "left" : "right"; -}, -calcPercentageDragged: function(e) { -return Math.abs(e / this.$.swipeableComponents.getBounds().width); -}, -swipe: function(e) { -this.swipeComplete = !0, this.animateSwipe(0, e); -}, -backOutSwipe: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; -this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; -}, -bounceItem: function(e) { -var t = this.$.swipeableComponents.getBounds(); -t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); -}, -slideAwayItem: function() { -var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; -this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -clearSwipeables: function() { -this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -completeSwipe: function(e) { -this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ -index: this.swipeIndex, -xDirection: this.swipeDirection -})), this.swipeIndex = null, this.swipeDirection = null; -}, -animateSwipe: function(e, t) { -var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; -this.stopAnimateSwipe(); -var u = enyo.bind(this, function() { -var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); -i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { -this.completeSwipe(); -}), this.completeSwipeDelayMS)); -}); -this.job = enyo.requestAnimationFrame(u); -}, -stopAnimateSwipe: function() { -this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); -} -}); - -// PulldownList.js - -enyo.kind({ -name: "enyo.PulldownList", -kind: "List", -touch: !0, -pully: null, -pulldownTools: [ { -name: "pulldown", -classes: "enyo-list-pulldown", -components: [ { -name: "puller", -kind: "Puller" -} ] -} ], -events: { -onPullStart: "", -onPullCancel: "", -onPull: "", -onPullRelease: "", -onPullComplete: "" -}, -handlers: { -onScrollStart: "scrollStartHandler", -onScrollStop: "scrollStopHandler", -ondragfinish: "dragfinish" -}, -pullingMessage: "Pull down to refresh...", -pulledMessage: "Release to refresh...", -loadingMessage: "Loading...", -pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", -pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", -loadingIconClass: "", -create: function() { -var e = { -kind: "Puller", -showing: !1, -text: this.loadingMessage, -iconClass: this.loadingIconClass, -onCreate: "setPully" -}; -this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); -}, -initComponents: function() { -this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); -}, -resetStrategyKind: function() { -return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; -}, -setPully: function(e, t) { -this.pully = t.originator; -}, -scrollStartHandler: function() { -this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; -}, -scroll: function(e, t) { -var n = this.inherited(arguments); -this.completingPull && this.pully.setShowing(!1); -var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); -return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; -}, -scrollStopHandler: function() { -this.completingPull && (this.completingPull = !1, this.doPullComplete()); -}, -dragfinish: function() { -if (this.firedPull) { -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); -} -}, -completePull: function() { -this.completingPull = !0; -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(this.pullHeight), e.start(); -}, -pullStart: function() { -this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); -}, -pull: function() { -this.setPulled(), this.doPull(); -}, -pullCancel: function() { -this.setPulling(), this.doPullCancel(); -}, -pullRelease: function() { -this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); -}, -setPulling: function() { -this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); -}, -setPulled: function() { -this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); -} -}), enyo.kind({ -name: "enyo.Puller", -classes: "enyo-puller", -published: { -text: "", -iconClass: "" -}, -events: { -onCreate: "" -}, -components: [ { -name: "icon" -}, { -name: "text", -tag: "span", -classes: "enyo-puller-text" -} ], -create: function() { -this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); -}, -textChanged: function() { -this.$.text.setContent(this.text); -}, -iconClassChanged: function() { -this.$.icon.setClasses(this.iconClass); -} -}); - -// AroundList.js - -enyo.kind({ -name: "enyo.AroundList", -kind: "enyo.List", -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "aboveClient" -}, { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "belowClient" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0px;" -} ] -} ], -aboveComponents: null, -initComponents: function() { -this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { -owner: this.owner -}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { -owner: this.owner -}); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; -n += r, t.applyStyle(this.pageBound, n + "px"); -}, -scrollToContentStart: function() { -var e = this.bottomUp ? this.belowHeight : this.aboveHeight; -this.setScrollPosition(e); -} -}); - -// Slideable.js - -enyo.kind({ -name: "enyo.Slideable", -kind: "Control", -published: { -axis: "h", -value: 0, -unit: "px", -min: 0, -max: 0, -accelerated: "auto", -overMoving: !0, -draggable: !0 -}, -events: { -onAnimateFinish: "", -onChange: "" -}, -preventDragPropagation: !1, -tools: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorComplete" -} ], -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -kDragScalar: 1, -dragEventProp: "dx", -unitModifier: !1, -canTransform: !1, -create: function() { -this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); -}, -initComponents: function() { -this.createComponents(this.tools), this.inherited(arguments); -}, -rendered: function() { -this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); -}, -resizeHandler: function() { -this.inherited(arguments), this.updateDragScalar(); -}, -canModifyUnit: function() { -if (!this.canTransform) { -var e = this.getInitialStyleValue(this.hasNode(), this.boundary); -e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); -} -}, -getInitialStyleValue: function(e, t) { -var n = enyo.dom.getComputedStyle(e); -return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; -}, -updateBounds: function(e, t) { -var n = {}; -n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); -}, -updateDragScalar: function() { -if (this.unit == "%") { -var e = this.getBounds()[this.dimension]; -this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); -} -}, -transformChanged: function() { -this.canTransform = enyo.dom.canTransform(); -}, -acceleratedChanged: function() { -enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); -}, -axisChanged: function() { -var e = this.axis == "h"; -this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; -}, -setInlineStyles: function(e, t) { -var n = {}; -this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); -}, -valueChanged: function(e) { -var t = this.value; -this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); -}, -getAnimator: function() { -return this.$.animator; -}, -isAtMin: function() { -return this.value <= this.calcMin(); -}, -isAtMax: function() { -return this.value >= this.calcMax(); -}, -calcMin: function() { -return this.min; -}, -calcMax: function() { -return this.max; -}, -clampValue: function(e) { -var t = this.calcMin(), n = this.calcMax(); -return Math.max(t, Math.min(e, n)); -}, -dampValue: function(e) { -return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); -}, -dampBound: function(e, t, n) { -var r = e; -return r * n < t * n && (r = t + (r - t) / 4), r; -}, -percentToPixels: function(e, t) { -return Math.floor(t / 100 * e); -}, -pixelsToPercent: function(e) { -var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; -return e / t * 100; -}, -shouldDrag: function(e) { -return this.draggable && e[this.shouldDragProp]; -}, -isOob: function(e) { -return e > this.calcMax() || e < this.calcMin(); -}, -dragstart: function(e, t) { -if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; -}, -drag: function(e, t) { -if (this.dragging) { -t.preventDefault(); -var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; -return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; -} -}, -dragfinish: function(e, t) { -if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; -}, -completeDrag: function(e) { -this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); -}, -isAnimating: function() { -return this.$.animator.isAnimating(); -}, -play: function(e, t) { -this.$.animator.play({ -startValue: e, -endValue: t, -node: this.hasNode() -}); -}, -animateTo: function(e) { -this.play(this.value, e); -}, -animateToMin: function() { -this.animateTo(this.calcMin()); -}, -animateToMax: function() { -this.animateTo(this.calcMax()); -}, -animateToMinMax: function(e) { -e ? this.animateToMin() : this.animateToMax(); -}, -animatorStep: function(e) { -return this.setValue(e.value), !0; -}, -animatorComplete: function(e) { -return this.doAnimateFinish(e), !0; -}, -toggleMinMax: function() { -this.animateToMinMax(!this.isAtMin()); -} -}); - -// Arranger.js - -enyo.kind({ -name: "enyo.Arranger", -kind: "Layout", -layoutClass: "enyo-arranger", -accelerated: "auto", -dragProp: "ddx", -dragDirectionProp: "xDirection", -canDragProp: "horizontal", -incrementalPoints: !1, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n._arranger = null; -this.inherited(arguments); -}, -arrange: function(e, t) {}, -size: function() {}, -start: function() { -var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; -if (this.incrementalPoints) { -var r = Math.abs(t - e) - 2, i = e; -while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; -} -n.push(this.container.toIndex); -}, -finish: function() {}, -calcArrangementDifference: function(e, t, n, r) {}, -canDragEvent: function(e) { -return e[this.canDragProp]; -}, -calcDragDirection: function(e) { -return e[this.dragDirectionProp]; -}, -calcDrag: function(e) { -return e[this.dragProp]; -}, -drag: function(e, t, n, r, i) { -var s = this.measureArrangementDelta(-e, t, n, r, i); -return s; -}, -measureArrangementDelta: function(e, t, n, r, i) { -var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; -return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; -}, -_arrange: function(e) { -this.containerBounds || this.reflow(); -var t = this.getOrderedControls(e); -this.arrange(t, e); -}, -arrangeControl: function(e, t) { -e._arranger = enyo.mixin(e._arranger || {}, t); -}, -flow: function() { -this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { -enyo.dom.accelerate(n, this.accelerated); -if (enyo.platform.safari) { -var r = n.children; -for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); -} -} -}, -reflow: function() { -var e = this.container.hasNode(); -this.containerBounds = e ? { -width: e.clientWidth, -height: e.clientHeight -} : {}, this.size(); -}, -flowArrangement: function() { -var e = this.container.arrangement; -if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); -}, -flowControl: function(e, t) { -enyo.Arranger.positionControl(e, t); -var n = t.opacity; -n != null && enyo.Arranger.opacifyControl(e, n); -}, -getOrderedControls: function(e) { -var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; -for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); -return this.controlsIndex = t, i; -}, -statics: { -positionControl: function(e, t, n) { -var r = n || "px"; -if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { -var i = t.left, s = t.top; -i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { -translateX: i || null, -translateY: s || null -}); -} else e.setBounds(t, n); -}, -opacifyControl: function(e, t) { -var n = t; -n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); -} -} -}); - -// CardArranger.js - -enyo.kind({ -name: "enyo.CardArranger", -kind: "Arranger", -layoutClass: "enyo-arranger enyo-arranger-fit", -calcArrangementDifference: function(e, t, n, r) { -return this.containerBounds.width; -}, -arrange: function(e, t) { -for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { -opacity: s -}); -}, -start: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); -this.inherited(arguments); -} -}); - -// CardSlideInArranger.js - -enyo.kind({ -name: "enyo.CardSlideInArranger", -kind: "CardArranger", -start: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -var i = this.container.fromIndex; -t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -arrange: function(e, t) { -var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; -for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { -left: l -}); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null -}); -this.inherited(arguments); -} -}); - -// CarouselArranger.js - -enyo.kind({ -name: "enyo.CarouselArranger", -kind: "Arranger", -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; -n.height -= t.top + t.bottom, n.width -= t.left + t.right; -var a; -for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); -if (a) { -var f = n.width - s; -a.width = f >= 0 ? f : a.width; -} -for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ -top: t.top, -bottom: t.bottom, -width: u.fit ? u.width : null -}); -}, -arrange: function(e, t) { -this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); -}, -arrangeNoWrap: function(e, t) { -var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; -for (n = u, i = 0; s = o[n]; n++) { -i += s.width + s.marginWidth; -if (i > a) break; -} -var f = a - i, l = 0; -if (f > 0) { -var c = u; -for (n = u - 1, r = 0; s = o[n]; n--) { -r += s.width + s.marginWidth; -if (f - r <= 0) { -l = f - r, u = n; -break; -} -} -} -var h, p; -for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { -left: -h -}) : (this.arrangeControl(s, { -left: Math.floor(p) -}), p += h); -}, -arrangeWrap: function(e, t) { -for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { -left: r -}), r += s.width + s.marginWidth; -}, -calcArrangementDifference: function(e, t, n, r) { -var i = Math.abs(e % this.c$.length); -return t[i].left - r[i].left; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// CollapsingArranger.js - -enyo.kind({ -name: "enyo.CollapsingArranger", -kind: "CarouselArranger", -peekWidth: 0, -size: function() { -this.clearLastSize(), this.inherited(arguments); -}, -clearLastSize: function() { -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); -}, -constructor: function() { -this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; -}, -arrange: function(e, t) { -var n = this.container.getPanels(); -for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { -left: i + u * this.peekWidth -}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { -left: i -}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { -left: i - t -}); -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels().length - 1; -return Math.abs(r[i].left - t[i].left); -}, -flowControl: function(e, t) { -this.inherited(arguments); -if (this.container.realtimeFit) { -var n = this.container.getPanels(), r = n.length - 1, i = n[r]; -e == i && this.fitControl(e, t.left); -} -}, -finish: function() { -this.inherited(arguments); -if (!this.container.realtimeFit && this.containerBounds) { -var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; -this.fitControl(r, t[n].left); -} -}, -fitControl: function(e, t) { -e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); -} -}); - -// DockRightArranger.js - -enyo.kind({ -name: "enyo.DockRightArranger", -kind: "Arranger", -basePanel: !1, -overlap: 0, -layoutWidth: 0, -constructor: function() { -this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; -n.width -= t.left + t.right; -var o = n.width, u = e.length; -this.container.transitionPositions = {}; -for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; -for (r = 0; s = e[r]; r++) { -r === 0 && this.container.basePanel && s.setBounds({ -width: o -}), s.setBounds({ -top: t.top, -bottom: t.bottom -}); -for (j = 0; s = e[j]; j++) { -var a; -if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { -if (r !== j) break; -var f = o > this.layoutWidth ? this.overlap : 0; -a = o - e[r].width + f; -} -this.container.transitionPositions[r + "." + j] = a; -} -if (j < u) { -var l = !1; -for (k = r + 1; k < u; k++) { -var f = 0; -if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { -f = e[r].width - this.overlap; -for (i = r; i < k; i++) { -var c = f + e[i + 1].width - this.overlap; -if (!(c < o)) { -f = o; -break; -} -f = c; -} -f = o - f; -} -this.container.transitionPositions[r + "." + k] = f; -} -} -} -}, -arrange: function(e, t) { -var n, r, i = this.container.getPanels(), s = this.container.clamp(t); -for (n = 0; r = i[n]; n++) { -var o = this.container.transitionPositions[n + "." + s]; -this.arrangeControl(r, { -left: o -}); -} -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; -return s; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// OtherArrangers.js - -enyo.kind({ -name: "enyo.LeftRightArranger", -kind: "Arranger", -margin: 40, -axisSize: "width", -offAxisSize: "height", -axisPosition: "left", -constructor: function() { -this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; -for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); -}, -start: function() { -this.inherited(arguments); -var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); -for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); -}, -arrange: function(e, t) { -var n, r, i, s; -if (this.container.getPanels().length == 1) { -s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); -return; -} -var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; -for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; -}, -calcArrangementDifference: function(e, t, n, r) { -if (this.container.getPanels().length == 1) return 0; -var i = Math.abs(e % this.c$.length); -return t[i][this.axisPosition] - r[i][this.axisPosition]; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.TopBottomArranger", -kind: "LeftRightArranger", -dragProp: "ddy", -dragDirectionProp: "yDirection", -canDragProp: "vertical", -axisSize: "height", -offAxisSize: "width", -axisPosition: "top" -}), enyo.kind({ -name: "enyo.SpiralArranger", -kind: "Arranger", -incrementalPoints: !0, -inc: 20, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; -for (var i = 0, s; s = e[i]; i++) s.setBounds({ -width: n, -height: r -}); -}, -arrange: function(e, t) { -var n = this.inc; -for (var r = 0, i = e.length, s; s = e[r]; r++) { -var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; -this.arrangeControl(s, { -left: o, -top: u -}); -} -}, -start: function() { -this.inherited(arguments); -var e = this.getOrderedControls(this.container.toIndex); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.controlWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.GridArranger", -kind: "Arranger", -incrementalPoints: !0, -colWidth: 100, -colHeight: 100, -size: function() { -var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; -for (var r = 0, i; i = e[r]; r++) i.setBounds({ -width: t, -height: n -}); -}, -arrange: function(e, t) { -var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; -for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { -left: n * a, -top: r * o -}); -}, -flowControl: function(e, t) { -this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.colWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// Panels.js - -enyo.kind({ -name: "enyo.Panels", -classes: "enyo-panels", -published: { -index: 0, -draggable: !0, -animate: !0, -wrap: !1, -arrangerKind: "CardArranger", -narrowFit: !0 -}, -events: { -onTransitionStart: "", -onTransitionFinish: "" -}, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onscroll: "domScroll" -}, -tools: [ { -kind: "Animator", -onStep: "step", -onEnd: "completed" -} ], -fraction: 0, -create: function() { -this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); -}, -rendered: function() { -this.inherited(arguments), enyo.makeBubble(this, "scroll"); -}, -domScroll: function(e, t) { -this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); -}, -initComponents: function() { -this.createChrome(this.tools), this.inherited(arguments); -}, -arrangerKindChanged: function() { -this.setLayoutKind(this.arrangerKind); -}, -narrowFitChanged: function() { -this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); -}, -destroy: function() { -this.destroying = !0, this.inherited(arguments); -}, -removeControl: function(e) { -this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); -}, -isPanel: function() { -return !0; -}, -flow: function() { -this.arrangements = [], this.inherited(arguments); -}, -reflow: function() { -this.arrangements = [], this.inherited(arguments), this.refresh(); -}, -getPanels: function() { -var e = this.controlParent || this; -return e.children; -}, -getActive: function() { -var e = this.getPanels(), t = this.index % e.length; -return t < 0 && (t += e.length), e[t]; -}, -getAnimator: function() { -return this.$.animator; -}, -setIndex: function(e) { -this.setPropertyValue("index", e, "indexChanged"); -}, -setIndexDirect: function(e) { -this.setIndex(e), this.completed(); -}, -previous: function() { -this.setIndex(this.index - 1); -}, -next: function() { -this.setIndex(this.index + 1); -}, -clamp: function(e) { -var t = this.getPanels().length - 1; -return this.wrap ? e : Math.max(0, Math.min(e, t)); -}, -indexChanged: function(e) { -this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ -startValue: this.fraction -})) : this.refresh())); -}, -step: function(e) { -this.fraction = e.value, this.stepTransition(); -}, -completed: function() { -this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -dragstart: function(e, t) { -if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; -}, -drag: function(e, t) { -this.dragging && (t.preventDefault(), this.dragTransition(t)); -}, -dragfinish: function(e, t) { -this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); -}, -dragstartTransition: function(e) { -if (!this.$.animator.isAnimating()) { -var t = this.fromIndex = this.index; -this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); -} else this.verifyDragTransition(e); -this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); -}, -dragTransition: function(e) { -var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; -a, this.fraction += u; -var f = this.fraction; -if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; -this.stepTransition(); -}, -dragfinishTransition: function(e) { -this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); -}, -verifyDragTransition: function(e) { -var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); -if (t > 0) { -var i = n; -n = r, r = i; -} -n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; -}, -refresh: function() { -this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -startTransition: function() { -this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); -}, -finishTransition: function() { -this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); -}, -fireTransitionStart: function() { -var e = this.startTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { -fromIndex: this.fromIndex, -toIndex: this.toIndex -}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); -}, -fireTransitionFinish: function() { -var e = this.finishTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { -fromIndex: this.lastIndex, -toIndex: this.index -}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; -}, -stepTransition: function() { -if (this.hasNode()) { -var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); -t -= n; -var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); -this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); -} -}, -fetchArrangement: function(e) { -return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; -}, -readArrangement: function(e) { -var t = []; -for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); -return t; -}, -statics: { -isScreenNarrow: function() { -return enyo.dom.getWindowWidth() <= 800; -}, -lerp: function(e, t, n) { -var r = []; -for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); -return r; -}, -lerpObject: function(e, t, n) { -var r = enyo.clone(e), i, s; -if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); -return r; -} -} -}); - -// Node.js - -enyo.kind({ -name: "enyo.Node", -published: { -expandable: !1, -expanded: !1, -icon: "", -onlyIconExpands: !1, -selected: !1 -}, -style: "padding: 0 0 0 16px;", -content: "Node", -defaultKind: "Node", -classes: "enyo-node", -components: [ { -name: "icon", -kind: "Image", -showing: !1 -}, { -kind: "Control", -name: "caption", -Xtag: "span", -style: "display: inline-block; padding: 4px;", -allowHtml: !0 -}, { -kind: "Control", -name: "extra", -tag: "span", -allowHtml: !0 -} ], -childClient: [ { -kind: "Control", -name: "box", -classes: "enyo-node-box", -Xstyle: "border: 1px solid orange;", -components: [ { -kind: "Control", -name: "client", -classes: "enyo-node-client", -Xstyle: "border: 1px solid lightblue;" -} ] -} ], -handlers: { -ondblclick: "dblclick" -}, -events: { -onNodeTap: "nodeTap", -onNodeDblClick: "nodeDblClick", -onExpand: "nodeExpand", -onDestroyed: "nodeDestroyed" -}, -create: function() { -this.inherited(arguments), this.selectedChanged(), this.iconChanged(); -}, -destroy: function() { -this.doDestroyed(), this.inherited(arguments); -}, -initComponents: function() { -this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); -}, -contentChanged: function() { -this.$.caption.setContent(this.content); -}, -iconChanged: function() { -this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); -}, -selectedChanged: function() { -this.addRemoveClass("enyo-selected", this.selected); -}, -rendered: function() { -this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); -}, -addNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent(n); -this.$.client.render(); -}, -addTextNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent({ -content: n -}); -this.$.client.render(); -}, -tap: function(e, t) { -return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; -}, -dblclick: function(e, t) { -return this.doNodeDblClick(), !0; -}, -toggleExpanded: function() { -this.setExpanded(!this.expanded); -}, -quickCollapse: function() { -this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); -var e = this.$.client.getBounds().height; -this.$.client.setBounds({ -top: -e -}); -}, -_expand: function() { -this.addClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), this.$.client.setBounds({ -top: 0 -}), setTimeout(enyo.bind(this, function() { -this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); -}), 225); -}, -_collapse: function() { -this.removeClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), setTimeout(enyo.bind(this, function() { -this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ -top: -e -}); -}), 25); -}, -expandedChanged: function(e) { -if (!this.expandable) this.expanded = !1; else { -var t = { -expanded: this.expanded -}; -this.doExpand(t), t.wait || this.effectExpanded(); -} -}, -effectExpanded: function() { -this.$.client && (this.expanded ? this._expand() : this._collapse()); -} -}); - -// ImageViewPin.js - -enyo.kind({ -name: "enyo.ImageViewPin", -kind: "enyo.Control", -published: { -highlightAnchorPoint: !1, -anchor: { -top: 0, -left: 0 -}, -position: { -top: 0, -left: 0 -} -}, -style: "position:absolute;z-index:1000;width:0px;height:0px;", -handlers: { -onPositionPin: "reAnchor" -}, -create: function() { -this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); -}, -styleClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); -}, -positionClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); -}, -highlightAnchorPointChanged: function() { -this.addRemoveClass("pinDebug", this.highlightAnchorPoint); -}, -anchorChanged: function() { -var e = null, t = null; -for (t in this.anchor) { -e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); -if (!e) continue; -this.anchor[t + "Coords"] = { -value: e[1], -units: e[2] || "px" -}; -} -}, -reAnchor: function(e, t) { -var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; -this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); -} -}); - -// ImageView.js - -enyo.kind({ -name: "enyo.ImageView", -kind: enyo.Scroller, -touchOverscroll: !1, -thumb: !1, -animate: !0, -verticalDragPropagation: !0, -horizontalDragPropagation: !0, -published: { -scale: "auto", -disableZoom: !1, -src: undefined -}, -events: { -onZoom: "" -}, -touch: !0, -preventDragPropagation: !1, -handlers: { -ondragstart: "dragPropagation" -}, -components: [ { -name: "animator", -kind: "Animator", -onStep: "zoomAnimationStep", -onEnd: "zoomAnimationEnd" -}, { -name: "viewport", -style: "overflow:hidden;min-height:100%;min-width:100%;", -classes: "enyo-fit", -ongesturechange: "gestureTransform", -ongestureend: "saveState", -ontap: "singleTap", -ondblclick: "doubleClick", -onmousewheel: "mousewheel", -components: [ { -kind: "Image", -ondown: "down" -} ] -} ], -create: function() { -this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); -}, -down: function(e, t) { -t.preventDefault(); -}, -dragPropagation: function(e, t) { -var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; -return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); -}, -mousewheel: function(e, t) { -t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; -var n = (this.maxScale - this.minScale) / 10, r = this.scale; -if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); -return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; -}, -srcChanged: function() { -this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); -}, -imageLoaded: function(e) { -this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); -}, -resizeHandler: function() { -this.inherited(arguments), this.$.image.src && this.scaleChanged(); -}, -scaleChanged: function() { -var e = this.hasNode(); -if (e) { -this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; -var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; -this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); -} -this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); -}, -imageError: function(e) { -enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); -}, -alignImage: function() { -if (this.fitAlignment && this.fitAlignment === "center") { -var e = this.getScrollBounds(); -this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); -} -}, -gestureTransform: function(e, t) { -this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); -}, -calcEventLocation: function(e) { -var t = { -x: 0, -y: 0 -}; -if (e && this.hasNode()) { -var n = this.node.getBoundingClientRect(); -t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); -} -return t; -}, -transformImage: function(e) { -this.tapped = !1; -var t = this.imageBounds || this.innerImageBounds(e); -this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px" -}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; -var n, r; -this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); -if (this.canTransform) { -var i = { -scale: e -}; -this.canAccelerate ? i = enyo.mixin({ -translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" -}, i) : i = enyo.mixin({ -translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" -}, i), enyo.dom.transform(this.$.image, i); -} else this.$.image.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px", -left: this.imageBounds.left + "px", -top: this.imageBounds.top + "px" -}); -this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); -}, -limitScale: function(e) { -return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; -}, -innerImageBounds: function(e) { -var t = this.originalWidth * e, n = this.originalHeight * e, r = { -x: 0, -y: 0, -transX: 0, -transY: 0 -}; -return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { -left: r.x + r.transX, -top: r.y + r.transY, -width: t, -height: n, -x: r.x, -y: r.y -}; -}, -saveState: function(e, t) { -var n = this.scale; -this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null; -}, -doubleClick: function(e, t) { -enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); -}, -singleTap: function(e, t) { -setTimeout(enyo.bind(this, function() { -this.tapped = !1; -}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; -}, -smartZoom: function(e, t) { -var n = this.hasNode(), r = this.$.image.hasNode(); -if (n && r && this.hasNode() && !this.disableZoom) { -var i = this.scale; -this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); -if (this.animate) { -var s = { -x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, -y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height -}; -this.$.animator.play({ -duration: 350, -ratioLock: s, -baseScale: i, -deltaScale: this.scale - i -}); -} else this.transformImage(this.scale), this.doZoom({ -scale: this.scale -}); -} -}, -zoomAnimationStep: function(e, t) { -var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; -this.transformImage(n); -}, -zoomAnimationEnd: function(e, t) { -this.doZoom({ -scale: this.scale -}), this.$.animator.ratioLock = undefined; -}, -positionClientControls: function(e) { -this.waterfallDown("onPositionPin", { -scale: e, -bounds: this.imageBounds -}); -} -}); - -// ImageCarousel.js - -enyo.kind({ -name: "enyo.ImageCarousel", -kind: enyo.Panels, -arrangerKind: "enyo.CarouselArranger", -defaultScale: "auto", -disableZoom: !1, -lowMemory: !1, -published: { -images: [] -}, -handlers: { -onTransitionStart: "transitionStart", -onTransitionFinish: "transitionFinish" -}, -create: function() { -this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); -}, -initContainers: function() { -for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ -name: "container" + e, -style: "height:100%; width:100%;" -}), this.$["container" + e].render()); -for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); -this.imageCount = this.images.length; -}, -loadNearby: function() { -var e = this.getBufferRange(); -for (var t in e) this.loadImageView(e[t]); -}, -getBufferRange: function() { -var e = []; -if (this.layout.containerBounds) { -var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; -o = this.index - 1, u = 0, a = n.width * t; -while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; -o = this.index, u = 0, a = n.width * (t + 1); -while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; -} -return e; -}, -reflow: function() { -this.inherited(arguments), this.loadNearby(); -}, -loadImageView: function(e) { -return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ -name: "image" + e, -kind: "ImageView", -scale: this.defaultScale, -disableZoom: this.disableZoom, -src: this.images[e], -verticalDragPropagation: !1, -style: "height:100%; width:100%;" -}, { -owner: this -}), this.$["image" + e].render())), this.$["image" + e]; -}, -setImages: function(e) { -this.setPropertyValue("images", e, "imagesChanged"); -}, -imagesChanged: function() { -this.initContainers(), this.loadNearby(); -}, -indexChanged: function() { -this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); -}, -transitionStart: function(e, t) { -if (t.fromIndex == t.toIndex) return !0; -}, -transitionFinish: function(e, t) { -this.loadNearby(), this.lowMemory && this.cleanupMemory(); -}, -getActiveImage: function() { -return this.getImageByIndex(this.index); -}, -getImageByIndex: function(e) { -return this.$["image" + e] || this.loadImageView(e); -}, -cleanupMemory: function() { -var e = getBufferRange(); -for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); -} -}); - -// runtime-machine.js - -runtimeMachine = { -_head: function(e, t, n) { -this._inflight = !0; -var r = document.createElement(e); -for (var i in t) r.setAttribute(i, t[i]); -return n && (r.innerText = n), this._headElt || (this._headElt = document.getElementsByTagName("head")[0]), this._headElt.appendChild(r), r; -}, -sheet: function(e) { -this._head("link", { -type: "text/css", -media: "screen", -rel: "stylesheet", -href: e -}); -}, -inject: function(e) { -this._head("script", { -type: "text/javascript" -}, e); -}, -_scripts: [], -script: function(e) { -this._inflight ? this._scripts.push(e) : this._script(e); -}, -_require: function(e) {}, -_script: function(e) { -this._inflight = !0; -var t = this._head("script", { -type: "text/javascript", -src: e -}), n = this; -enyo.platform.ie && enyo.platform.ie <= 8 ? t.onreadystatechange = function() { -if (t.readyState === "complete" || t.readyState === "loaded") t.onreadystatechange = "", n._loaded(e); -} : (t.onload = function() { -n._loaded(e); -}, t.onerror = function() { -n._error(e); -}); -}, -_continue: function() { -this._inflight = !1; -var e = this._scripts.pop(); -e && this._script(e); -}, -_loaded: function(e) { -this._continue(); -}, -_error: function(e) { -this._continue(); -} -}; - -// AnalyzerDebug.js - -enyo.kind({ -name: "AnalyzerDebug", -kind: null, -debug: !1, -_level: 0, -methodName: function(e) { -var t = this.getStackInfo(3 + (e || 0)); -return t = t.replace(/ .http:.*$/g, ""), t = t.replace(/^.*.enyo.kind/g, this.kindName), t += " ", t.substr(0, 30); -}, -getCurrentStackInfo: function(e) { -return " current: " + this.getStackInfo(3 + (e || 0)); -}, -getPreviousStackInfo: function(e) { -return " previous: " + this.getStackInfo(4 + (e || 0)); -}, -getStackInfo: function(e) { -try { -throw new Error; -} catch (t) { -var n = t.stack; -if (n) { -var r = n.split("\n"); -return r[e]; -} -return "(stack trace not available)"; -} -}, -showLevel: function() { -return "#####################################".substr(0, this._level) + " "; -}, -incremLevel: function() { -return this._level++, this.showLevel() + " --> "; -}, -decremLevel: function() { -var e = this.showLevel() + " <-- "; -return this._level--, e; -}, -showIterator: function(e) { -return e ? "[" + e.ID + "/" + e.i + "] " : ""; -}, -logMethodEntry: function(e, t) { -t = t || "", enyo.log(this.methodName(1) + this.incremLevel() + this.showIterator(e) + t + this.getPreviousStackInfo(1)); -}, -logMethodExit: function(e, t) { -t = t || "", enyo.log(this.methodName(1) + this.decremLevel() + this.showIterator(e) + t + this.getCurrentStackInfo(1)); -}, -logProcessing: function(e, t) { -enyo.log(this.methodName(1) + this.showLevel() + this.showIterator(e) + "PROCESSING kind: " + t.kind + " >>" + t.token + "<< line: " + t.line + this.getCurrentStackInfo(1)); -}, -logIterMsg: function(e, t) { -enyo.log(this.methodName(1) + this.showLevel() + this.showIterator(e) + t + this.getPreviousStackInfo(1)); -}, -logMsg: function(e) { -enyo.log(this.methodName(1) + this.showLevel() + e + this.getPreviousStackInfo(1)); -}, -statics: { -_debugEnabled: !1 -} -}); - -// Walker.js - -enyo.kind({ -name: "Walker", -kind: enyo.Component, -published: { -verbose: !1 -}, -events: { -onProgress: "", -onFinish: "" -}, -walk: function(e, t) { -return this.verbose && this.log("inPath: " + e + " resolver: ", t), this.loader = new enyo.loaderFactory(runtimeMachine, t), this.loader.loadScript = function() {}, this.loader.loadSheet = function() {}, this.loader.verbose = this.verbose, this.loader.report = enyo.bind(this, "walkReport"), this.loader.finish = enyo.bind(this, "walkFinish"), enyo.loader = this.loader, t ? (path = t.rewrite(e), this.verbose && path !== e && this.log("inPathResolver: " + e + " ==> " + path)) : (path = enyo.path.rewrite(e), this.verbose && path !== e && this.log("enyo.path: " + e + " ==> " + path)), enyo.asyncMethod(this.loader, "load", path), this.async = new enyo.Async; -}, -walkReport: function(e, t) { -this.doProgress({ -action: e, -name: t -}); -}, -walkFinish: function() { -this.modules = this.loader.modules, this.async.respond({ -modules: this.modules -}), this.doFinish({ -modules: this.modules -}); -} -}); - -// Reader.js - -enyo.kind({ -name: "Reader", -kind: enyo.Async, -go: function(e) { -return this.modules = e.modules, this.moduleIndex = 0, enyo.asyncMethod(this, "nextModule"), this; -}, -nextModule: function() { -var e = this.modules[this.moduleIndex++]; -e ? this.loadModule(e) : this.modulesFinished(); -}, -loadModule: function(e) { -enyo.xhr.request({ -url: e.path, -callback: enyo.bind(this, "moduleLoaded", e) -}); -}, -moduleLoaded: function(e, t) { -this.addModule(e, t), this.nextModule(); -}, -addModule: function(e, t) { -t && t.length && (e.code = t); -}, -modulesFinished: function() { -this.respond({ -modules: this.modules -}); -} -}); - -// Iterator.js - -enyo.kind({ -name: "Iterator", -kind: null, -i: -1, -nodes: null, -constructor: function(e) { -this.ID = Iterator._objectCount++, this.stream = e; -}, -statics: { -_objectCount: 0 -}, -next: function() { -return this.i++, this._read(); -}, -prev: function() { -return this.i--, this._read(); -}, -_read: function(e) { -return this.past = this.stream[this.i - 1], this.value = this.stream[this.i], this.future = this.stream[this.i + 1], this.value; -} -}); - -// Lexer.js - -enyo.kind({ -name: "AbstractLexer", -kind: null, -constructor: function(e) { -if (e) return this.start(e), this.finish(), this.r; -}, -p0: 0, -p: 0, -start: function(e) { -this.s = e, this.l = this.s.length, this.r = [], this.d = "", this.p0 = 0, this.p = 0, this.n = 0, this.analyze(); -}, -search: function(e) { -var t = e.global ? e : new RegExp(e.source, "g"); -return t.lastIndex = this.p, this.m = t.exec(this.s), this.p = this.m ? this.m.index : -1, t.lastIndex != this.p0 && (this.d = this.s.charAt(this.p)); -}, -lookahead: function(e) { -return this.s.charAt(this.p + e); -}, -getToken: function() { -return this.s.slice(this.p0, this.p); -}, -tokenize: function(e) { -this.p += e || 0; -}, -pushToken: function(e, t, n) { -this.tokenize(t); -var r = this.getToken(); -if (!r && !n) return {}; -var i = (r.match(/\n/g) || []).length, s = { -kind: e, -token: r, -start: this.p0, -end: this.p, -line: this.n, -height: i -}; -return this.r.push(s), this.n += i, this.p0 = this.p, s; -}, -tossToken: function(e) { -this.tokenize(e), this.p0 = this.p; -}, -finish: function() { -this.pushToken("gah"); -} -}), enyo.kind({ -name: "Lexer", -kind: AbstractLexer, -symbols: "(){}[];,:<>+-=*/&", -operators: [ "++", "--", "+=", "-=", "==", "!=", "<=", ">=", "===", "&&", "||", '"', "'" ], -keywords: [ "function", "new", "return", "if", "else", "while", "do", "break", "continue", "switch", "case", "var" ], -constructor: function(e) { -return this.buildPattern(), this.inherited(arguments); -}, -buildPattern: function() { -var e = '"(?:\\\\"|[^"])*?"', t = "'(?:\\\\'|[^'])*?'", n = e + "|" + t, r = "\\b(?:" + this.keywords.join("|") + ")\\b", i = "[\\" + this.symbols.split("").join("\\") + "]", s = []; -for (var o = 0, u; u = this.operators[o]; o++) s.push("\\" + u.split("").join("\\")); -s = s.join("|"), i = s + "|" + i; -var a = [ '\\\\"|\\\\/', n, r, "\\/\\/", "\\/\\*", i, "\\s" ]; -this.matchers = [ "doSymbol", "doString", "doKeyword", "doLineComment", "doCComment", "doSymbol", "doWhitespace" ], this.pattern = "(" + a.join(")|(") + ")"; -}, -analyze: function() { -var e = new RegExp(this.pattern, "gi"); -while (this.search(e)) this.pushToken("identifier"), this.process(this.matchers), this.pushToken("identifier"); -}, -process: function(e) { -for (var t = 0, n; n = e[t]; t++) if (this.m[t + 1] && this[n]) { -this[n].apply(this); -return; -} -this.doSymbol(); -}, -doWhitespace: function() { -this.tokenize(1), this.search(/\S/g), this.pushToken("ws"), this.r.pop(); -}, -doEscape: function() { -this.tokenize(2); -}, -doLiteral: function() { -this.tossToken(1); -var e = this.d, t = new RegExp("\\" + e + "|\\\\", "g"); -while (this.search(t)) switch (this.d) { -case "\\": -this.doEscape(); -break; -default: -this.pushToken("literal", 0, !0).delimiter = e, this.tossToken(1); -return; -} -}, -doSymbol: function() { -this.pushToken(this.d == ";" || this.d == "," ? "terminal" : "symbol", this.m[0].length); -}, -doKeyword: function() { -this.pushToken("keyword", this.m[0].length); -}, -doLineComment: function() { -this.tokenize(2), this.search(/[\r\n]/g) && this.tokenize(0), this.pushToken("comment"); -}, -doCComment: function() { -this.tokenize(2); -var e = 1; -while (e && this.search(/\/\*|\*\//g)) e += this.d == "/" ? 1 : this.d == "*" ? -1 : 0, this.tokenize(2); -this.pushToken("comment"); -}, -doString: function() { -this.pushToken("string", this.m[0].length); -} -}); - -// Parser.js - -enyo.kind({ -name: "Parser", -kind: "AnalyzerDebug", -constructor: function(e) { -return this.debug = AnalyzerDebug._debugEnabled, this.parse(e); -}, -parse: function(e) { -var t = [], n = new Iterator(e); -while (n.next()) n.value.kind !== "ws" && t.push(n.value); -var n = new Iterator(t); -return this.walk(n); -}, -combine: function(e) { -var t = ""; -for (var n = 0, r; r = e[n]; n++) t += r.token; -return t; -}, -walk: function(e, t) { -this.debug && this.logMethodEntry(e, "inState " + t + " >>" + JSON.stringify(e.value) + "<<"); -var n = [], r; -try { -while (e.next()) { -r = e.value, this.debug && this.logProcessing(e, r); -if (r.kind == "ws") continue; -if (r.kind == "comment") r.kind = "comment"; else if (t == "array") { -if (r.kind == "terminal") continue; -e.prev(); -var i = e.value; -r = { -kind: "element", -token: "expr", -children: this.walk(e, "expression") -}; -if (e.value && e.value.token == "]" || e.value && e.value === i) return r.children.length && n.push(r), this.debug && this.logMethodExit(e), n; -} else if (r.token == "[") r.kind = "array", r.children = this.walk(e, r.kind), e.value ? r.end = e.value.end : this.debug && this.logIterMsg(e, "No end token for array?"); else { -if (t == "expression" && r.token == "]") return this.debug && this.logMethodExit(e), n; -if (r.token == "var") r.kind = "var", r.children = this.walk(e, "expression"); else { -if (r.kind == "terminal" && (t == "expression" || t == "var")) return this.debug && this.logMethodExit(e), n; -if (r.kind == "terminal") continue; -if (r.token == "{") { -r.kind = "block", this.debug && this.logIterMsg(e, "PROCESS BLOCK - START"), r.children = this.walk(e, r.kind), this.debug && this.logIterMsg(e, "PROCESS BLOCK - END"), e.value ? r.end = e.value.end : this.debug && this.logIterMsg(e, "No end token for block?"), r.commaTerminated = this.isCommaTerminated(e); -if (t == "expression" || t == "function") return n.push(r), this.debug && this.logMethodExit(e), n; -} else { -if (t == "expression" && (r.token == "}" || r.token == ")")) return e.prev(), this.debug && this.logMethodExit(e), n; -if (t == "block" && r.token == "}") return this.debug && this.logMethodExit(e), n; -if (r.token == "=" || r.token == ":" && t != "expression") { -var s = n.pop(); -s.kind == "identifier" ? (s.op = r.token, s.kind = "assignment", s.children = this.walk(e, "expression"), e.value && e.value.kind == "terminal" && (s.commaTerminated = e.value.token === ",", e.prev()), r = s) : n.push(s); -} else if (r.token == "(") r.kind = "association", r.children = this.walk(e, r.kind); else { -if (t == "association" && r.token == ")") return this.debug && this.logMethodExit(e), n; -if (r.token == "function") { -r.kind = "function", this.debug && this.logIterMsg(e, "PROCESS FUNCTION - START"), r.children = this.walk(e, r.kind), this.debug && this.logIterMsg(e, "PROCESS FUNCTION - END"), (!e.value || e.value.kind !== "symbol" || e.value.token !== "}") && this.debug && this.logIterMsg(e, "No end token for function?"); -if (t !== "expression" && r.children && r.children.length && r.children[0].kind == "identifier") { -this.debug && this.logIterMsg(e, "C-Style function"), r.name = r.children[0].token, r.children.shift(); -var o = { -kind: "assignment", -token: r.name, -children: [ r ] -}; -r = o; -} -if (t == "expression" || t == "function") return r.commaTerminated = this.isCommaTerminated(e), n.push(r), this.debug && this.logMethodExit(e), n; -} -} -} -} -} -this.debug && this.logIterMsg(e, "PUSH NODE"), n.push(r); -} -} catch (u) { -console.error(u); -} -return this.debug && this.logMethodExit(e), n; -}, -isCommaTerminated: function(e) { -commaPresent = !1; -var t = e.next(); -return t && (commaPresent = t.kind === "terminal" && t.token === ","), e.prev(), commaPresent; -} -}); - -// Documentor.js - -enyo.kind({ -name: "Documentor", -kind: "AnalyzerDebug", -group: "public", -constructor: function(e) { -return this.comment = [], this.debug = AnalyzerDebug._debugEnabled, this.parse(e); -}, -parse: function(e) { -var t = new Iterator(e); -return this.walk(t); -}, -walk: function(e, t) { -var n = [], r, i; -this.debug && this.logMethodEntry(e, "inState " + t + " >>" + JSON.stringify(e.value) + "<<"); -while (e.next()) { -r = e.value, this.debug && this.logProcessing(e, r); -if (r.kind == "comment") this.cook_comment(r.token); else if (r.token == "enyo.kind" && e.future.kind == "association") i = this.cook_kind(e); else if (r.kind == "assignment") i = this.cook_assignment(e); else if (r.kind == "association" && r.children && r.children.length == 1 && r.children[0].kind == "function") { -var s = r.children[0]; -if (s.children && s.children.length == 2) { -var o = s.children[1], u = this.walk(new Iterator(o.children)); -n = n.concat(u); -} -e.next(); -} -i && (n.push(i), i = null); -} -return this.debug && this.logMethodExit(e), n; -}, -cook_kind: function(e) { -this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); -var t = function(e, t) { -var n = Documentor.indexByName(e, t), r; -return n >= 0 && (r = e[n], e.splice(r, 1)), r && r.value && r.value.length && r.value[0].token; -}, n = this.make("kind", e.value); -e.next(); -var r = e.value.children; -return r && r[0] && r[0].kind == "block" && (n.properties = this.cook_block(r[0].children), n.name = Documentor.stripQuotes(t(n.properties, "name") || ""), n.superkind = Documentor.stripQuotes(t(n.properties, "kind") || "enyo.Control"), n.superkind == "null" && (n.superkind = null), n.block = { -start: r[0].start, -end: r[0].end -}), this.debug && this.logMethodExit(e), n; -}, -cook_block: function(e) { -this.debug && this.logMethodEntry(); -var t = []; -for (var n = 0, r; r = e[n]; n++) { -this.debug && this.logProcessing(null, r); -if (r.kind == "comment") this.cook_comment(r.token); else if (r.kind == "assignment") { -var i = this.make("property", r); -r.children && (i.value = [ this.walkValue(new Iterator(r.children)) ], r.commaTerminated === undefined ? (i.commaTerminated = r.children[0].commaTerminated || !1, r.children[0].commaTerminated === undefined && this.debug && this.logMsg("NO COMMA TERMINATED INFO")) : i.commaTerminated = r.commaTerminated), t.push(i); -} -} -return this.debug && this.logMethodExit(), t; -}, -walkValue: function(e, t) { -this.debug && this.logMethodEntry(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"); -while (e.next()) { -var n = e.value, r; -this.debug && this.logProcessing(e, n); -if (n.kind != "comment") { -if (n.kind == "block") return r = this.make("block", n), r.properties = this.cook_block(n.children), this.debug && this.logMethodExit(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"), r; -if (n.kind == "array") return r = this.cook_array(e), this.debug && this.logMethodExit(e), r; -if (n.kind == "function") return r = this.cook_function(e), this.debug && this.logMethodExit(e, "inState: " + t + " >>" + JSON.stringify(e.value) + "<<"), r; -r = this.make("expression", n); -var i = n.token; -while (e.next()) i += e.value.token; -return r.token = i, this.debug && this.logMethodExit(e), r; -} -this.cook_comment(n.token); -} -this.debug && this.logMethodExit(e); -}, -cook_function: function(e) { -this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); -var t = e.value, n = this.make("expression", t); -return n.commaTerminated = t.commaTerminated, n.arguments = enyo.map(t.children[0].children, function(e) { -return e.token; -}), this.debug && this.logMethodExit(e), n; -}, -cook_array: function(e) { -this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); -var t = e.value, n = this.make("array", t), r = t.children; -if (r) { -var i = []; -for (var s = 0, o, u; o = r[s]; s++) o.children && (u = this.walkValue(new Iterator(o.children)), u && i.push(u)); -n.properties = i; -} -return this.debug && this.logMethodExit(e), n; -}, -cook_assignment: function(e) { -this.debug && this.logMethodEntry(e, ">>" + JSON.stringify(e.value) + "<<"); -var t = e.value, n = this.make("global", t); -return t.children && (t.children[0] && t.children[0].token == "function" && (n.type = "function"), n.value = [ this.walkValue(new Iterator(t.children)) ]), this.debug && this.logMethodExit(), n; -}, -make: function(e, t) { -return { -line: t.line, -start: t.start, -end: t.end, -height: t.height, -token: t.token, -name: t.token, -type: e, -group: this.group, -comment: this.consumeComment() -}; -}, -commentRx: /\/\*\*([\s\S]*)\*\/|\/\/\*(.*)/m, -cook_comment: function(e) { -this.debug && this.logMethodEntry(); -var t = e.match(this.commentRx); -if (t) { -t = t[1] ? t[1] : t[2]; -var n = this.extractPragmas(t); -this.honorPragmas(n); -} -this.debug && this.logMethodExit(); -}, -extractPragmas: function(e) { -var t = /^[*\s]*@[\S\s]*/g, n = [], r = e; -return r.length && (r = e.replace(t, function(e) { -var t = e.slice(2); -return n.push(t), ""; -}), r.length && this.comment.push(r)), n; -}, -honorPragmas: function(e) { -var t = { -"protected": 1, -"public": 1 -}; -for (var n = 0, r; r = e[n]; n++) t[r] && (this.group = r); -}, -consumeComment: function() { -var e = this.comment.join(" "); -this.comment = []; -var t = Documentor.removeIndent(e); -return t; -}, -statics: { -indexByProperty: function(e, t, n) { -for (var r = 0, i; i = e[r]; r++) if (i[t] == n) return r; -return -1; -}, -findByProperty: function(e, t, n) { -return e[this.indexByProperty(e, t, n)]; -}, -indexByName: function(e, t) { -return this.indexByProperty(e, "name", t); -}, -findByName: function(e, t) { -return e[this.indexByName(e, t)]; -}, -stripQuotes: function(e) { -var t = e.charAt(0), n = t == '"' || t == "'" ? 1 : 0, r = e.charAt(e.length - 1), i = r == '"' || r == "'" ? -1 : 0; -return n || i ? e.slice(n, i) : e; -}, -removeIndent: function(e) { -var t = 0, n = e.split(/\r?\n/), r, i; -for (r = 0; (i = n[r]) != null; r++) if (i.length > 0) { -t = i.search(/\S/), t < 0 && (t = i.length); -break; -} -if (t) for (r = 0; (i = n[r]) != null; r++) n[r] = i.slice(t); -return n.join("\n"); -} -} -}); - -// Indexer.js - -enyo.kind({ -name: "Indexer", -kind: null, -group: "public", -constructor: function() { -this.objects = []; -}, -debug: !1, -findByName: function(e) { -return Documentor.findByProperty(this.objects, "name", e); -}, -findByTopic: function(e) { -return Documentor.findByProperty(this.objects, "topic", e); -}, -search: function(e, t, n) { -var r = enyo.filter(this.objects, e, n); -return enyo.map(r, t, n); -}, -addModules: function(e) { -enyo.forEach(e, this.addModule, this), this.objects.sort(Indexer.nameCompare); -}, -addModule: function(e) { -this.debug && enyo.log("Indexer.addModule(): + " + e.path), this.indexModule(e), this.mergeModule(e); -}, -mergeModule: function(e) { -this.objects.push(e), this.objects = this.objects.concat(e.objects), enyo.forEach(e.objects, this.mergeProperties, this); -}, -mergeProperties: function(e) { -e.properties ? this.objects = this.objects.concat(e.properties) : e.value && e.value[0] && e.value[0].properties && (this.objects = this.objects.concat(e.value[0].properties)); -}, -indexModule: function(e) { -e.type = "module", e.name = e.path ? e.path.replace("lib/", "") : e.label + "/" + e.rawPath, e.objects = new Documentor(new Parser(new Lexer(e.code))), this.indexObjects(e); -}, -indexObjects: function(e) { -enyo.forEach(e.objects, function(t) { -t.module = e, this.indexObject(t); -}, this); -}, -indexObject: function(e) { -switch (e.type) { -case "kind": -this.indexKind(e); -} -this.indexProperties(e); -}, -indexProperties: function(e) { -var t = e.properties || e.value && e.value[0] && e.value[0].properties; -enyo.forEach(t, function(t) { -t.object = e, t.topic = t.object.name ? t.object.name + "::" + t.name : t.name; -}, this); -}, -indexKind: function(e) { -this.listComponents(e), this.indexInheritance(e); -}, -indexInheritance: function(e) { -e.superkinds = this.listSuperkinds(e), e.allProperties = this.listInheritedProperties(e); -}, -listSuperkinds: function(e) { -var t = [], n; -while (e && e.superkind) n = e.superkind, e = this.findByName(n), e || (e = this.findByName("enyo." + n), e && (n = "enyo." + n)), t.push(n); -return t; -}, -listInheritedProperties: function(e) { -var t = [], n = {}; -for (var r = e.superkinds.length - 1, i; i = e.superkinds[r]; r--) { -var s = this.findByName(i); -s && this.mergeInheritedProperties(s.properties, n, t); -} -return this.mergeInheritedProperties(e.properties, n, t), t.sort(Indexer.nameCompare), t; -}, -mergeInheritedProperties: function(e, t, n) { -for (var r = 0, i; i = e[r]; r++) { -var s = t.hasOwnProperty(i.name) && t[i.name]; -s ? (i.overrides = s, n[enyo.indexOf(s, n)] = i) : n.push(i), t[i.name] = i; -} -}, -listComponents: function(e) { -e.components = this._listComponents(e, [], {}); -var t = Documentor.findByName(e.properties, "components"); -t && t.value && (e.componentsBlockStart = t.value[0].start, e.componentsBlockEnd = t.value[0].end); -}, -_listComponents: function(e, t, n) { -var r = Documentor.findByName(e.properties, "components"); -if (r && r.value && r.value.length) { -var i = r.value[0].properties; -for (var s = 0, o; o = i[s]; s++) { -var u = Documentor.findByName(o.properties, "name"); -u && (u = Documentor.stripQuotes(u.value[0].token || "")); -var a = Documentor.findByName(o.properties, "kind"); -a = Documentor.stripQuotes(a && a.value[0].token || "Control"); -if (!u) { -var f = a.split(".").pop(); -u = enyo.uncap(f), n[u] ? u += ++n[u] : n[u] = 1; -} -o.kind = a, o.name = u, t.push(o), this._listComponents(o, t, n); -} -} -return t; -}, -statics: { -nameCompare: function(e, t) { -var n = e.name.toLowerCase(), r = t.name.toLowerCase(); -return n < r ? -1 : n > r ? 1 : 0; -} -} -}); - -// Analyzer.js - -enyo.kind({ -name: "Analyzer", -kind: "Component", -debug: !1, -events: { -onIndexReady: "" -}, -create: function() { -this.index = new Indexer, this.inherited(arguments); -}, -analyze: function(e, t) { -this.walk(e, t); -}, -walk: function(e, t) { -var n = [], r, i = function(s, o) { -if (o) { -this.debug && enyo.log("Analyzer.walk.next() - inData: ", o); -for (var u = 0; u < o.modules.length; ++u) o.modules[u].label = r; -n = n.concat(o.modules); -} -var a = e.shift(), f = ""; -a ? (this.debug && enyo.log("Analyzer.walk.next() - path: " + a), enyo.isString(a) || (r = a.label, a = a.path), (new Walker).walk(a, t).response(this, i)) : this.walkFinished(n); -}; -i.call(this); -}, -walkFinished: function(e) { -this.read(e); -}, -read: function(e) { -(new Reader).go({ -modules: e -}).response(this, function(e, t) { -this.indexModules(t.modules); -}); -}, -indexModules: function(e) { -this.index.addModules(e), this.doIndexReady(); -} -}); - -// KindHelper.js - -enyo.kind({ -name: "Analyzer.KindHelper", -kind: "enyo.Component", -published: { -definition: null -}, -checkDefAvail: function() { -if (!this.definition) throw "No definition provided"; -}, -getEvents: function() { -this.checkDefAvail(); -var e = []; -obj = this.definition.properties; -for (i = 0; i < obj.length; i++) if (obj[i].token === "events") { -p = obj[i].value[0].properties; -for (var t = 0; t < p.length; t++) { -var n = p[t].name; -e.push(n); -} -} -return e; -}, -getPublished: function() { -this.checkDefAvail(); -var e = []; -obj = this.definition.properties; -for (i = 0; i < obj.length; i++) if (obj[i].token === "published") { -p = obj[i].value[0].properties; -for (var t = 0; t < p.length; t++) { -var n = p[t].name; -e.push(n); -} -} -return e; -} -}); - -// foss/showdown-v0.9/compressed/showdown.js - -var Showdown = {}; - -Showdown.converter = function() { -var e, t, n, r = 0; -this.makeHtml = function(r) { -return e = new Array, t = new Array, n = new Array, r = r.replace(/~/g, "~T"), r = r.replace(/\$/g, "~D"), r = r.replace(/\r\n/g, "\n"), r = r.replace(/\r/g, "\n"), r = "\n\n" + r + "\n\n", r = O(r), r = r.replace(/^[ \t]+$/mg, ""), r = s(r), r = i(r), r = u(r), r = L(r), r = r.replace(/~D/g, "$$"), r = r.replace(/~T/g, "~"), r; -}; -var i = function(n) { -var n = n.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, function(n, r, i, s, o) { -return r = r.toLowerCase(), e[r] = T(i), s ? s + o : (o && (t[r] = o.replace(/"/g, """)), ""); -}); -return n; -}, s = function(e) { -e = e.replace(/\n/g, "\n\n"); -var t = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del", n = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"; -return e = e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, o), e = e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, o), e = e.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, o), e = e.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g, o), e = e.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, o), e = e.replace(/\n\n/g, "\n"), e; -}, o = function(e, t) { -var r = t; -return r = r.replace(/\n\n/g, "\n"), r = r.replace(/^\n/, ""), r = r.replace(/\n+$/g, ""), r = "\n\n~K" + (n.push(r) - 1) + "K\n\n", r; -}, u = function(e) { -e = d(e); -var t = y("
    "); -return e = e.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, t), e = e.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, t), e = e.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, t), e = m(e), e = g(e), e = S(e), e = s(e), e = x(e), e; -}, a = function(e) { -return e = b(e), e = f(e), e = N(e), e = h(e), e = l(e), e = C(e), e = T(e), e = E(e), e = e.replace(/ +\n/g, "
    \n"), e; -}, f = function(e) { -var t = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; -return e = e.replace(t, function(e) { -var t = e.replace(/(.)<\/?code>(?=.)/g, "$1`"); -return t = M(t, "\\`*_"), t; -}), e; -}, l = function(e) { -return e = e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, c), e = e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, c), e = e.replace(/(\[([^\[\]]+)\])()()()()()/g, c), e; -}, c = function(n, r, i, s, o, u, a, f) { -f == undefined && (f = ""); -var l = r, c = i, h = s.toLowerCase(), p = o, d = f; -if (p == "") { -h == "" && (h = c.toLowerCase().replace(/ ?\n/g, " ")), p = "#" + h; -if (e[h] != undefined) p = e[h], t[h] != undefined && (d = t[h]); else { -if (!(l.search(/\(\s*\)$/m) > -1)) return l; -p = ""; -} -} -p = M(p, "*_"); -var v = '", v; -}, h = function(e) { -return e = e.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, p), e = e.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, p), e; -}, p = function(n, r, i, s, o, u, a, f) { -var l = r, c = i, h = s.toLowerCase(), p = o, d = f; -d || (d = ""); -if (p == "") { -h == "" && (h = c.toLowerCase().replace(/ ?\n/g, " ")), p = "#" + h; -if (e[h] == undefined) return l; -p = e[h], t[h] != undefined && (d = t[h]); -} -c = c.replace(/"/g, """), p = M(p, "*_"); -var v = '' + c + '" + a(t) + ""); -}), e = e.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, function(e, t) { -return y("

    " + a(t) + "

    "); -}), e = e.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, function(e, t, n) { -var r = t.length; -return y("" + a(n) + ""); -}), e; -}, v, m = function(e) { -e += "~0"; -var t = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; -return r ? e = e.replace(t, function(e, t, n) { -var r = t, i = n.search(/[*+-]/g) > -1 ? "ul" : "ol"; -r = r.replace(/\n{2,}/g, "\n\n\n"); -var s = v(r); -return s = s.replace(/\s+$/, ""), s = "<" + i + ">" + s + "\n", s; -}) : (t = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g, e = e.replace(t, function(e, t, n, r) { -var i = t, s = n, o = r.search(/[*+-]/g) > -1 ? "ul" : "ol", s = s.replace(/\n{2,}/g, "\n\n\n"), u = v(s); -return u = i + "<" + o + ">\n" + u + "\n", u; -})), e = e.replace(/~0/, ""), e; -}; -v = function(e) { -return r++, e = e.replace(/\n{2,}$/, "\n"), e += "~0", e = e.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, function(e, t, n, r, i) { -var s = i, o = t, f = n; -return o || s.search(/\n{2,}/) > -1 ? s = u(A(s)) : (s = m(A(s)), s = s.replace(/\n$/, ""), s = a(s)), "
  • " + s + "
  • \n"; -}), e = e.replace(/~0/g, ""), r--, e; -}; -var g = function(e) { -return e += "~0", e = e.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g, function(e, t, n) { -var r = t, i = n; -return r = w(A(r)), r = O(r), r = r.replace(/^\n+/g, ""), r = r.replace(/\n+$/g, ""), r = "
    " + r + "\n
    ", y(r) + i; -}), e = e.replace(/~0/, ""), e; -}, y = function(e) { -return e = e.replace(/(^\n+|\n+$)/g, ""), "\n\n~K" + (n.push(e) - 1) + "K\n\n"; -}, b = function(e) { -return e = e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function(e, t, n, r, i) { -var s = r; -return s = s.replace(/^([ \t]*)/g, ""), s = s.replace(/[ \t]*$/g, ""), s = w(s), t + "" + s + ""; -}), e; -}, w = function(e) { -return e = e.replace(/&/g, "&"), e = e.replace(//g, ">"), e = M(e, "*_{}[]\\", !1), e; -}, E = function(e) { -return e = e.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, "$2"), e = e.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, "$2"), e; -}, S = function(e) { -return e = e.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, function(e, t) { -var n = t; -return n = n.replace(/^[ \t]*>[ \t]?/gm, "~0"), n = n.replace(/~0/g, ""), n = n.replace(/^[ \t]+$/gm, ""), n = u(n), n = n.replace(/(^|\n)/g, "$1 "), n = n.replace(/(\s*

    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 ZSV=`|o|&s+m?^$49RAnC{{`^0FP}7Ec+T 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 literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/assets/uranus.jpg b/lib/layout/imageview/samples/assets/uranus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0a8fbc2c554e41f658e73dcd642849b1c2a82838 GIT binary patch literal 46984 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%0DD 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 literal 0 HcmV?d00001 diff --git a/lib/layout/imageview/samples/package.js b/lib/layout/imageview/samples/package.js new file mode 100644 index 0000000..c6c33c8 --- /dev/null +++ b/lib/layout/imageview/samples/package.js @@ -0,0 +1,6 @@ +enyo.depends( + "ImageViewSample.js", + "ImageViewSample.css", + "ImageCarouselSample.js", + "ImageCarouselSample.css" +); \ No newline at end of file diff --git a/lib/layout/imageview/source/ImageCarousel.js b/lib/layout/imageview/source/ImageCarousel.js new file mode 100644 index 0000000..1edacf6 --- /dev/null +++ b/lib/layout/imageview/source/ImageCarousel.js @@ -0,0 +1,208 @@ +/** + _enyo.ImageCarousel_ is an enyo.Panels that + uses enyo.CarouselArranger as its + arrangerKind. An ImageCarousel dynamically creates and loads instances of + enyo.ImageView as needed, creating a gallery + of images. + + {kind:"ImageCarousel", images:[ + "assets/mercury.jpg", + "assets/venus.jpg", + "assets/earth.jpg", + "assets/mars.jpg", + "assets/jupiter.jpg", + "assets/saturn.jpg", + "assets/uranus.jpg", + "assets/neptune.jpg" + ], defaultScale:"auto"}, + + All of the events (_onload_, _onerror_, and _onZoom_) from the contained + ImageView objects are bubbled up to the ImageCarousel, which also inherits + the _onTransitionStart_ and _onTransitionFinish_ events from _enyo.Panels_. + + The _images_ property is an array containing the file paths of the images in + the gallery. The _images_ array may be altered and updated at any time, and + the current index may be manipulated at runtime via the inherited + _getIndex()_ and _setIndex()_ functions. + + Note that it's best to specify a size for the ImageCarousel in order to + avoid complications. +*/ + +enyo.kind({ + name: "enyo.ImageCarousel", + kind: enyo.Panels, + arrangerKind: "enyo.CarouselArranger", + /** + The default scale value to be applied to each ImageView. Can be "auto", + "width", "height", or any positive numeric value. + */ + defaultScale: "auto", + //* If true, ImageView instances are created with zooming disabled. + disableZoom: false, + /** + If true, any ImageViews that are not in the immediate viewing area + (i.e., the currently active image and the first image on either + side of it) will be destroyed to free up memory. This has the benefit of + using minimal memory (which is good for mobile devices), but has the + downside that, if you want to view the images again, the ImageViews will + have to be re-created and the images re-fetched (thus increasing the + number of image-related GET calls). Defaults to false. + */ + lowMemory: false, + published: { + //* Array of image source file paths + images:[] + }, + //* @protected + handlers: { + onTransitionStart: "transitionStart", + onTransitionFinish: "transitionFinish" + }, + create: function() { + this.inherited(arguments); + this.imageCount = this.images.length; + if(this.images.length>0) { + this.initContainers(); + this.loadNearby(); + } + }, + initContainers: function() { + for(var i=0; i=0 && x<=xEnd) { + c = this.$["container" + i]; + x+= c.width + c.marginWidth; + range.unshift(i); + i--; + } + // get the upper range + i=this.index; + x=0; + xEnd = bounds.width * (prefetchRange + 1); + while (i=0 && index<=this.images.length-1) { + if(!this.$["image" + index]) { + this.$["container" + index].createComponent({ + name: "image" + index, + kind: "ImageView", + scale: this.defaultScale, + disableZoom: this.disableZoom, + src: this.images[index], + verticalDragPropagation: false, + style: "height:100%; width:100%;" + }, {owner: this}); + this.$["image" + index].render(); + } else { + if(this.$["image" + index].src != this.images[index]) { + this.$["image" + index].setSrc(this.images[index]); + this.$["image" + index].setScale(this.defaultScale); + this.$["image" + index].setDisableZoom(this.disableZoom); + } + } + } + return this.$["image" + index]; + }, + setImages: function(inImages) { + // always invoke imagesChanged because this is an array property + // which might otherwise seem to be the same object + this.setPropertyValue("images", inImages, "imagesChanged"); + }, + imagesChanged: function() { + this.initContainers(); + this.loadNearby(); + }, + indexChanged: function() { + this.loadNearby(); + if(this.lowMemory) { + this.cleanupMemory(); + } + this.inherited(arguments); + }, + transitionStart: function(inSender, inEvent) { + if(inEvent.fromIndex==inEvent.toIndex) + return true; //prevent from bubbling if there's no change + }, + transitionFinish: function(inSender, inEvent) { + this.loadNearby(); + if(this.lowMemory) { + this.cleanupMemory(); + } + }, + //* @public + //* Returns the currently displayed ImageView. + getActiveImage: function() { + return this.getImageByIndex(this.index); + }, + //* Returns the ImageView with the specified index. + getImageByIndex: function(index) { + return this.$["image" + index] || this.loadImageView(index); + }, + /** + Destroys any ImageView objects that are not in the immediate viewing + area (i.e., the currently active image and the first image on either + side of it) to free up memory. If you set the Image Carousel's + _lowMemory_ property to true, this function will be called automatically + as needed. + */ + cleanupMemory: function() { + var buffer = getBufferRange(); + for(var i=0; ienyo.ScrollThumb + indicators, disable zoom animation, allow panning overscroll (with a + bounce-back effect), and control the propagation of drag events, all via + boolean properties. + + Note that it's best to specify a size for the ImageView in order to avoid + complications. +*/ + +enyo.kind({ + name: "enyo.ImageView", + kind: enyo.Scroller, + /** + If true, allows for overscrolling during panning, with a bounce-back + effect. (Defaults to false.) + */ + touchOverscroll: false, + /** + If true, a ScrollThumb is used to indicate scroll position/bounds. + (Defaults to false.) + */ + thumb: false, + /** + If true (the default), the zoom action triggered by a double-tap (or + double-click) will be animated. + */ + animate: true, + /** + If true (the default), allows propagation of vertical drag events when + already at the top or bottom of the pannable area. + */ + verticalDragPropagation: true, + /** + If true (the default), allows propagation of horizontal drag events when + already at the left or right edge of the pannable area. + */ + horizontalDragPropagation: true, + published: { + /** + The scale at which the image should be displayed. It may be any + positive numeric value or one of the following key words (which will + be resolved to a value dynamically): + + * "auto": Fits the image to the size of the ImageView + * "width": Fits the image the width of the ImageView + * "height": Fits the image to the height of the ImageView + * "fit": Fits the image to the height and width of the ImageView. + Overflow of the larger dimension is cropped and the image is centered + on this axis + */ + scale: "auto", + //* Disables the zoom functionality + disableZoom: false, + //* The file path of the image to be displayed + src: undefined + }, + events: { + /** + Fires whenever the user adjusts the zoom of the image, via + double-tap/double-click, mousewheel, or pinch-zoom. + + _inEvent.scale_ contains the new scaling factor for the image. + */ + onZoom:"" + }, + //* @protected + touch: true, + preventDragPropagation: false, + handlers: { + ondragstart: "dragPropagation" + }, + components:[ + {name: "animator", kind: "Animator", onStep: "zoomAnimationStep", onEnd: "zoomAnimationEnd"}, + {name:"viewport", style: "overflow:hidden;min-height:100%;min-width:100%;", classes: "enyo-fit", + ongesturechange: "gestureTransform", ongestureend: "saveState", ontap: "singleTap", + ondblclick: "doubleClick", onmousewheel: "mousewheel", + components: [ + {kind:"Image", ondown: "down"} + ] + } + ], + create: function() { + this.inherited(arguments); + this.canTransform = enyo.dom.canTransform(); + if(!this.canTransform) { + this.$.image.applyStyle("position", "relative"); + } + this.canAccelerate = enyo.dom.canAccelerate(); + //offscreen buffer image to get initial image dimensions + //before displaying a scaled down image that can fit in the container + this.bufferImage = new Image(); + this.bufferImage.onload = enyo.bind(this, "imageLoaded"); + this.bufferImage.onerror = enyo.bind(this, "imageError"); + this.srcChanged(); + // For image view, disable drags during gesture (to fix flicker: ENYO-1208) + this.getStrategy().setDragDuringGesture(false); + // Needed to kickoff pin redrawing (otherwise they wont' redraw on intitial scroll) + if(this.getStrategy().$.scrollMath) { + this.getStrategy().$.scrollMath.start(); + } + }, + down: function(inSender, inEvent) { + // Fix to prevent image drag in Firefox + inEvent.preventDefault(); + }, + dragPropagation: function(inSender, inEvent) { + // Propagate drag events at the edges of the image as desired by the + // verticalDragPropagation and horizontalDragPropagation properties + var bounds = this.getStrategy().getScrollBounds(); + var verticalEdge = ((bounds.top===0 && inEvent.dy>0) || (bounds.top>=bounds.maxTop-2 && inEvent.dy<0)); + var horizontalEdge = ((bounds.left===0 && inEvent.dx>0) || (bounds.left>=bounds.maxLeft-2 && inEvent.dx<0)); + return !((verticalEdge && this.verticalDragPropagation) || (horizontalEdge && this.horizontalDragPropagation)); + }, + mousewheel: function(inSender, inEvent) { + inEvent.pageX |= (inEvent.clientX + inEvent.target.scrollLeft); + inEvent.pageY |= (inEvent.clientY + inEvent.target.scrollTop); + var zoomInc = (this.maxScale - this.minScale)/10; + var oldScale = this.scale; + if((inEvent.wheelDelta > 0) || (inEvent.detail < 0)) { //zoom in + this.scale = this.limitScale(this.scale + zoomInc); + } else if((inEvent.wheelDelta < 0) || (inEvent.detail > 0)) { //zoom out + this.scale = this.limitScale(this.scale - zoomInc); + } + this.eventPt = this.calcEventLocation(inEvent); + this.transformImage(this.scale); + if(oldScale != this.scale) { + this.doZoom({scale:this.scale}); + } + this.ratioX = this.ratioY = null; + // Prevent default scroll wheel action and prevent event from bubbling up to to touch scroller + inEvent.preventDefault(); + return true; + }, + srcChanged: function() { + if(this.src && this.src.length>0 && this.bufferImage && this.src!=this.bufferImage.src) { + this.bufferImage.src = this.src; + } + }, + imageLoaded: function(inEvent) { + this.originalWidth = this.bufferImage.width; + this.originalHeight = this.bufferImage.height; + + //scale to fit before setting src, so unscaled image isn't visible + this.scaleChanged(); + this.$.image.setSrc(this.bufferImage.src); + + //Needed to ensure scroller contents height/width is calculated correctly when contents use enyo-fit + enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"); + + this.positionClientControls(this.scale); + this.alignImage(); + }, + resizeHandler: function() { + this.inherited(arguments); + // Once we've loaded the image, adjust the min/max scale anytime we resize + if (this.$.image.src) { + this.scaleChanged(); + } + }, + scaleChanged: function() { + var containerNode = this.hasNode(); + if(containerNode) { + this.containerWidth = containerNode.clientWidth; + this.containerHeight = containerNode.clientHeight; + var widthScale = this.containerWidth / this.originalWidth; + var heightScale = this.containerHeight / this.originalHeight; + this.minScale = Math.min(widthScale, heightScale); + this.maxScale = (this.minScale*3 < 1) ? 1 : this.minScale*3; + //resolve any keyword scale values to solid numeric values + if(this.scale == "auto") { + this.scale = this.minScale; + } else if(this.scale == "width") { + this.scale = widthScale; + } else if(this.scale == "height") { + this.scale = heightScale; + } else if(this.scale == "fit") { + this.fitAlignment = "center"; + this.scale = Math.max(widthScale, heightScale); + } else { + this.maxScale = Math.max(this.maxScale, this.scale); + this.scale = this.limitScale(this.scale); + } + } + this.eventPt = this.calcEventLocation(); + this.transformImage(this.scale); + }, + imageError: function(inEvent) { + enyo.error("Error loading image: " + this.src); + //bubble up the error event + this.bubble("onerror", inEvent); + }, + alignImage: function() { + if (this.fitAlignment && this.fitAlignment === "center") { + var sb = this.getScrollBounds(); + this.setScrollLeft( sb.maxLeft / 2); + this.setScrollTop( sb.maxTop / 2); + } + }, + gestureTransform: function(inSender, inEvent) { + this.eventPt = this.calcEventLocation(inEvent); + this.transformImage(this.limitScale(this.scale * inEvent.scale)); + }, + calcEventLocation: function(inEvent) { + //determine the target coordinates on the imageview from an event + var eventPt = {x: 0, y:0}; + if(inEvent && this.hasNode()) { + var rect = this.node.getBoundingClientRect(); + eventPt.x = Math.round((inEvent.pageX - rect.left) - this.imageBounds.x); + eventPt.x = Math.max(0, Math.min(this.imageBounds.width, eventPt.x)); + eventPt.y = Math.round((inEvent.pageY - rect.top) - this.imageBounds.y); + eventPt.y = Math.max(0, Math.min(this.imageBounds.height, eventPt.y)); + } + return eventPt; + }, + transformImage: function(scale) { + this.tapped = false; + + var prevBounds = this.imageBounds || this.innerImageBounds(scale); + this.imageBounds = this.innerImageBounds(scale); + + //style cursor if needed to indicate the image is movable + if(this.scale>this.minScale) { + this.$.viewport.applyStyle("cursor", "move"); + } else { + this.$.viewport.applyStyle("cursor", null); + } + this.$.viewport.setBounds({width: this.imageBounds.width + "px", height: this.imageBounds.height + "px"}); + + //determine the exact ratio where on the image was tapped + this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / prevBounds.width; + this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / prevBounds.height; + var scrollLeft, scrollTop; + if(this.$.animator.ratioLock) { //locked for smartzoom + scrollLeft = (this.$.animator.ratioLock.x * this.imageBounds.width) - (this.containerWidth / 2); + scrollTop = (this.$.animator.ratioLock.y * this.imageBounds.height) - (this.containerHeight / 2); + } else { + scrollLeft = (this.ratioX * this.imageBounds.width) - this.eventPt.x; + scrollTop = (this.ratioY * this.imageBounds.height) - this.eventPt.y; + } + scrollLeft = Math.max(0, Math.min((this.imageBounds.width - this.containerWidth), scrollLeft)); + scrollTop = Math.max(0, Math.min((this.imageBounds.height - this.containerHeight), scrollTop)); + + if(this.canTransform) { + var params = {scale: scale}; + // translate needs to be first, or scale and rotation will not be in the correct spot + if(this.canAccelerate) { + //translate3d rounded values to avoid distortion; ref: http://martinkool.com/post/27618832225/beware-of-half-pixels-in-css + params = enyo.mixin({translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px"}, params); + } else { + params = enyo.mixin({translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px"}, params); + } + enyo.dom.transform(this.$.image, params); + } else { //pretty much just IE8 + //use top/left and width/height to adjust + this.$.image.setBounds({width: this.imageBounds.width + "px", height: this.imageBounds.height + "px", + left:this.imageBounds.left + "px", top:this.imageBounds.top + "px"}); + } + + //adjust scroller to new position that keeps ratio with the new image size + this.setScrollLeft(scrollLeft); + this.setScrollTop(scrollTop); + + this.positionClientControls(scale); + + //this.stabilize(); + }, + limitScale: function(scale) { + if(this.disableZoom) { + scale = this.scale; + } else if(scale > this.maxScale) { + scale = this.maxScale; + } else if(scale < this.minScale) { + scale = this.minScale; + } + return scale; + }, + innerImageBounds: function(scale) { + var width = this.originalWidth * scale; + var height = this.originalHeight * scale; + var offset = {x:0, y:0, transX:0, transY:0}; + if(width + + + + FlyweightRepeater Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/FlyweightRepeaterSample.js b/lib/layout/list/samples/FlyweightRepeaterSample.js new file mode 100644 index 0000000..5733a97 --- /dev/null +++ b/lib/layout/list/samples/FlyweightRepeaterSample.js @@ -0,0 +1,59 @@ +enyo.kind({ + name: "enyo.sample.FlyweightRepeaterSample", + kind: "FittableRows", + classes: "flyweight-repeater-sample enyo-fit onyx", + components: [ + {kind: "onyx.Toolbar", components: [ + {content: "FlyweightRepeater Result"} + ]}, + {name:"result", style:"padding:12px; font-size: 20px;", content: "Nothing selected yet."}, + {kind: "enyo.Scroller", fit: true, components: [ + {name:"repeater", kind:"enyo.FlyweightRepeater", classes:"flyweight-repeater-sample-list", count: 26, onSetupItem: "setupItem", components: [ + {name: "item", classes:"flyweight-repeater-sample-item"} + ]} + ]} + ], + handlers: { + onSelect: "itemSelected" + }, + people: [ + {name: "Andrew"}, + {name: "Betty"}, + {name: "Christopher"}, + {name: "Donna"}, + {name: "Ephraim"}, + {name: "Frankie"}, + {name: "Gerald"}, + {name: "Heather"}, + {name: "Ingred"}, + {name: "Jack"}, + {name: "Kevin"}, + {name: "Lucy"}, + {name: "Matthew"}, + {name: "Noreen"}, + {name: "Oscar"}, + {name: "Pedro"}, + {name: "Quentin"}, + {name: "Ralph"}, + {name: "Steven"}, + {name: "Tracy"}, + {name: "Uma"}, + {name: "Victor"}, + {name: "Wendy"}, + {name: "Xin"}, + {name: "Yulia"}, + {name: "Zoltan"} + ], + setupItem: function(inSender, inEvent) { + var index = inEvent.index; + this.$.item.setContent((index+1) + ". " + this.people[index].name); + this.$.item.applyStyle("background", (inEvent.selected? "dodgerblue":"lightgray")); + }, + itemSelected: function(inSender, inEvent) { + var index = inEvent.index; + var count = inEvent.flyweight.count; + if(index>=0 && index * { + display: inline-block; + vertical-align: middle; +} +.list-sample-around-avatar { + width: 32px; + height: 32px; + padding-right: 10px; +} +.list-sample-around-name { + font-size: 16px; + font-weight: bold; + color: white; +} +.list-sample-around-description { + font-size: 12px; + color: silver; +} +.list-sample-around-remove-button { + float: right; + display: none; +} +/* divider */ +.list-sample-around-divider { + background-color: #666; + font-size: 14px; + font-weight: bold; + padding: 8px 14px; +} +/* popup */ +.list-sample-around-popup { + width: 280px; +} +.list-sample-around-popup > * { + display: block; + margin: 10px 10px; +} +.list-sample-around-populate-button { + float: right; + margin-top: 25px; +} +.list-sample-around-label { + display: inline-block; + width: 120px; + padding-right: 10px; +} \ No newline at end of file diff --git a/lib/layout/list/samples/ListAroundSample.html b/lib/layout/list/samples/ListAroundSample.html new file mode 100644 index 0000000..35422fe --- /dev/null +++ b/lib/layout/list/samples/ListAroundSample.html @@ -0,0 +1,23 @@ + + + + + AroundList Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListAroundSample.js b/lib/layout/list/samples/ListAroundSample.js new file mode 100644 index 0000000..6350161 --- /dev/null +++ b/lib/layout/list/samples/ListAroundSample.js @@ -0,0 +1,211 @@ +enyo.kind({ + name: "enyo.sample.ListAroundSample", + kind: "FittableRows", + classes: "enyo-fit enyo-unselectable", + components: [ + {name: "list", kind: "AroundList", classes: "list-sample-around", fit: true, multiSelect: true, onSetupItem: "setupItem", aboveComponents: [ + {kind: "onyx.Toolbar", layoutKind: "FittableColumnsLayout", components: [ + {kind: "onyx.InputDecorator", fit: true, noStretch: true, layoutKind: "FittableColumnsLayout", components: [ + {kind: "onyx.Input", placeholder: "Search...", fit: true, oninput: "searchInputChange"}, + {kind: "Image", src: "assets/search-input-search.png", style: "height: 20px; width: 20px;"} + ]} + ]} + ], components: [ + {name: "divider", classes: "list-sample-around-divider"}, + {name: "item", kind: "AroundListContactItem", classes: "list-sample-around-item enyo-border-box", onRemove: "removeTap"} + ]}, + {name: "popup", kind: "onyx.Popup", modal: true, centered: true, classes: "list-sample-around-popup", components: [ + {components: [ + {content: "count:", classes: "list-sample-around-label"}, + {kind: "onyx.InputDecorator", components: [ + {name: "countInput", kind: "onyx.Input", style: "width: 80px", value: 100} + ]} + ]}, + {components: [ + {content: "rowsPerPage:", classes: "list-sample-around-label"}, + {kind: "onyx.InputDecorator", components: [ + {name: "rowsPerPageInput", kind: "onyx.Input", style: "width: 80px", value: 50} + ]} + ]}, + {components: [ + {content: "hide divider:", classes: "list-sample-around-label"}, + {name: "hideDividerCheckbox", kind: "onyx.Checkbox"} + ]}, + {components: [ + {kind: "onyx.Button", content: "populate list", classes: "list-sample-around-populate-button", ontap: "populateList"} + ]} + ]} + ], + rendered: function() { + this.inherited(arguments); + this.populateList(); + }, + setupItem: function(inSender, inEvent) { + var i = inEvent.index; + var data = this.filter ? this.filtered : this.db; + var item = data[i]; + // content + this.$.item.setContact(item); + // selection + this.$.item.setSelected(inSender.isSelected(i)); + // divider + if (!this.hideDivider) { + var d = item.name[0]; + var prev = data[i-1]; + var showd = d != (prev && prev.name[0]); + this.$.divider.setContent(d); + this.$.divider.canGenerate = showd; + this.$.item.applyStyle("border-top", showd ? "none" : null); + } + }, + refreshList: function() { + if (this.filter) { + this.filtered = this.generateFilteredData(this.filter); + this.$.list.setCount(this.filtered.length); + } else { + this.$.list.setCount(this.db.length); + } + this.$.list.refresh(); + }, + addItem: function() { + var item = this.generateItem(enyo.cap(this.$.newContactInput.getValue())); + var i = 0; + for (var di; (di=this.db[i]); i++) { + if (di.name > item.name) { + this.db.splice(i, 0, item); + break; + } + } + this.refreshList(); + this.$.list.scrollToRow(i); + }, + removeItem: function(inIndex) { + this._removeItem(inIndex); + this.refreshList(); + this.$.list.getSelection().deselect(inIndex); + }, + _removeItem: function(inIndex) { + var i = this.filter ? this.filtered[inIndex].dbIndex : inIndex; + this.db.splice(i, 1); + }, + removeTap: function(inSender, inEvent) { + this.removeItem(inEvent.index); + return true; + }, + populateList: function() { + this.$.popup.hide(); + this.createDb(this.$.countInput.getValue()); + this.$.list.setCount(this.db.length); + this.$.list.setRowsPerPage(this.$.rowsPerPageInput.getValue()); + // + this.hideDivider = this.$.hideDividerCheckbox.getValue(); + this.$.divider.canGenerate = !this.hideDivider; + // + this.$.list.reset(); + this.$.list.scrollToContentStart(); + }, + createDb: function(inCount) { + this.db = []; + for (var i=0; i b.name) return 1; + else return 0; + }); + }, + showSetupPopup: function() { + this.$.popup.show(); + }, + searchInputChange: function(inSender) { + enyo.job(this.id + ":search", enyo.bind(this, "filterList", inSender.getValue()), 200); + }, + filterList: function(inFilter) { + if (inFilter != this.filter) { + this.filter = inFilter; + this.filtered = this.generateFilteredData(inFilter); + this.$.list.setCount(this.filtered.length); + this.$.list.reset(); + } + }, + generateFilteredData: function(inFilter) { + var re = new RegExp("^" + inFilter, "i"); + var r = []; + for (var i=0, d; (d=this.db[i]); i++) { + if (d.name.match(re)) { + d.dbIndex = i; + r.push(d); + } + } + return r; + } +}); + +var avatars = [ + "angel.png", + "astrologer.png", + "athlete.png", + "baby.png", + "clown.png", + "devil.png", + "doctor.png", + "dude.png", + "dude2.png", + "dude3.png", + "dude4.png", + "dude5.png", + "dude6.png" +]; +var titles = [ + "Regional Data Producer", + "Internal Markets Administrator", + "Central Solutions Producer", + "Dynamic Program Executive", + "Direct Configuration Executive", + "International Marketing Assistant", + "District Research Consultant", + "Lead Intranet Coordinator", + "Central Accountability Director", + "Product Web Assistant" +]; + +// It's convenient to create a kind for the item we'll render in the contacts list. +enyo.kind({ + name: "AroundListContactItem", + events: { + onRemove: "" + }, + components: [ + {name: "avatar", kind: "Image", classes: "list-sample-around-avatar"}, + {components: [ + {name: "name", classes: "list-sample-around-name"}, + {name: "title", classes: "list-sample-around-description"}, + {content: "(415) 711-1234", classes: "list-sample-around-description"} + ]}, + {name: "remove", kind: "onyx.IconButton", classes: "list-sample-around-remove-button", src: "assets/remove-icon.png", ontap: "removeTap"} + ], + setContact: function(inContact) { + this.$.name.setContent(inContact.name); + this.$.avatar.setSrc(inContact.avatar); + this.$.title.setContent(inContact.title); + }, + setSelected: function(inSelected) { + this.addRemoveClass("list-sample-around-item-selected", inSelected); + this.$.remove.applyStyle("display", inSelected ? "inline-block" : "none"); + }, + removeTap: function(inSender, inEvent) { + this.doRemove(inEvent); + return true; + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.css b/lib/layout/list/samples/ListBasicSample.css new file mode 100644 index 0000000..5ff4102 --- /dev/null +++ b/lib/layout/list/samples/ListBasicSample.css @@ -0,0 +1,28 @@ +.list-sample { + background-color: gray; +} +.list-sample-list { + width: 50%; + min-width: 300px; + max-width: 600px; + margin: auto; + background-color: #eee; +} +.list-sample-item { + border: 1px solid silver; + padding: 18px; + font-size: 18px; + font-weight: bold; +} +.list-sample-index { + float: right; + font-size: 16px; + font-weight: normal; +} +.list-sample-selected { + background-color: #c4e3fe; +} +/* needed to make onyx-highlight more specific for highlighting to work */ +.onyx-highlight.list-sample-selected { + background-color: #dedfdf; +} \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.html b/lib/layout/list/samples/ListBasicSample.html new file mode 100644 index 0000000..f261a09 --- /dev/null +++ b/lib/layout/list/samples/ListBasicSample.html @@ -0,0 +1,22 @@ + + + + + Basic List Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.js b/lib/layout/list/samples/ListBasicSample.js new file mode 100644 index 0000000..056473c --- /dev/null +++ b/lib/layout/list/samples/ListBasicSample.js @@ -0,0 +1,27 @@ +enyo.kind({ + name: "enyo.sample.ListBasicSample", + classes: "list-sample enyo-fit", + components: [ + {name: "list", kind: "List", count: 20000, multiSelect: false, classes: "enyo-fit list-sample-list", onSetupItem: "setupItem", components: [ + {name: "item", classes: "list-sample-item enyo-border-box", components: [ + {name: "index", classes: "list-sample-index"}, + {name: "name"} + ]} + ]} + ], + names: [], + setupItem: function(inSender, inEvent) { + // this is the row we're setting up + var i = inEvent.index; + // make some mock data if we have none for this row + if (!this.names[i]) { + this.names[i] = makeName(5, 10, '', ''); + } + var n = this.names[i]; + var ni = ("00000000" + i).slice(-7); + // apply selection style if inSender (the list) indicates that this row is selected. + this.$.item.addRemoveClass("list-sample-selected", inSender.isSelected(i)); + this.$.name.setContent(n); + this.$.index.setContent(ni); + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.css b/lib/layout/list/samples/ListContactsSample.css new file mode 100644 index 0000000..a880df4 --- /dev/null +++ b/lib/layout/list/samples/ListContactsSample.css @@ -0,0 +1,57 @@ +.list-sample-contacts { + color: white; +} +.list-sample-contacts-list { + background: url(assets/bg.png); +} +/* item */ +.list-sample-contacts-item { + height: 100px; + border-top: 1px solid silver; + padding: 12px 16px; + background-color: #333333; +} +.list-sample-contacts-item-selected { + background: #226B9A url(assets/item-hilite.png) repeat-x bottom; +} +.list-sample-contacts-item > * { + display: inline-block; + vertical-align: middle; +} +.list-sample-contacts-avatar { + width: 32px; + height: 32px; + padding-right: 10px; +} +.list-sample-contacts-description { + font-size: 12px; + color: silver; +} +.list-sample-contacts-remove-button { + float: right; + display: none; +} +/* divider */ +.list-sample-contacts-divider { + background-color: #666; + font-size: 14px; + font-weight: bold; + padding: 8px 14px; +} +/* popup */ +.list-sample-contacts-popup { + width: 280px; +} +.list-sample-contacts-popup > * { + display: block; + margin: 10px 10px; +} +.list-sample-contacts-populate-button { + float: right; + margin-top: 25px; +} +.list-sample-contacts-label { + display: inline-block; + width: 120px; + padding-right: 10px; +} \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.html b/lib/layout/list/samples/ListContactsSample.html new file mode 100644 index 0000000..d288f50 --- /dev/null +++ b/lib/layout/list/samples/ListContactsSample.html @@ -0,0 +1,23 @@ + + + + + Contacts List Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.js b/lib/layout/list/samples/ListContactsSample.js new file mode 100644 index 0000000..e41ce97 --- /dev/null +++ b/lib/layout/list/samples/ListContactsSample.js @@ -0,0 +1,261 @@ +enyo.kind({ + name: "enyo.sample.ListContactsSample", + kind: "FittableRows", + classes: "list-sample-contacts enyo-fit", + components: [ + {kind: "onyx.MoreToolbar", layoutKind: "FittableColumnsLayout", style: "height: 55px;", components: [ + {kind: "onyx.Button", content: "setup", ontap: "showSetupPopup"}, + {kind: "onyx.InputDecorator", components: [ + {name: "newContactInput", kind: "onyx.Input", value: "Frankie Fu"} + ]}, + {kind: "onyx.Button", content: "new contact", ontap: "addItem"}, + {fit: true}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", placeholder: "Search...", style: "width: 140px;", oninput: "searchInputChange"}, + {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px;"} + ]}, + {kind: "onyx.Button", content: "remove selected", ontap: "removeSelected"} + ]}, + {kind: "List", classes: "list-sample-contacts-list enyo-unselectable", fit: true, multiSelect: true, + onSetupItem: "setupItem", components: [ + {name: "divider", classes: "list-sample-contacts-divider"}, + {name: "item", kind: "ContactItem", classes: "list-sample-contacts-item enyo-border-box", onRemove: "removeTap"} + ] + }, + {name: "popup", kind: "onyx.Popup", modal: true, centered: true, classes: "list-sample-contacts-popup", components: [ + {components: [ + {style: "display:inline-block", components:[ + {content: "count:", classes: "list-sample-contacts-label"}, + {name: "countOutput", style: "display:inline-block;", content: "200"} + ]}, + {kind: "onyx.Slider", value: 4, onChanging: "countSliderChanging", onChange: "countSliderChanging"} + ]}, + {components: [ + {content: "rowsPerPage:", classes: "list-sample-contacts-label"}, + {name: "rowsPerPageOutput", style: "display:inline-block;", content: "50"}, + {kind: "onyx.Slider", value: 10, onChanging: "rowsSliderChanging", onChange: "rowsSliderChanging"} + ]}, + {components: [ + {content: "hide divider:", classes: "list-sample-contacts-label"}, + {name: "hideDividerCheckbox", kind: "onyx.Checkbox"} + ]}, + {components: [ + {kind: "onyx.Button", content: "populate list", classes: "list-sample-contacts-populate-button", ontap: "populateList"} + ]} + ]} + ], + rendered: function() { + this.inherited(arguments); + this.populateList(); + }, + setupItem: function(inSender, inEvent) { + var i = inEvent.index; + var data = this.filter ? this.filtered : this.db; + var item = data[i]; + // content + this.$.item.setContact(item); + // selection + this.$.item.setSelected(inSender.isSelected(i)); + // divider + if (!this.hideDivider) { + var d = item.name[0]; + var prev = data[i-1]; + var showd = d != (prev && prev.name[0]); + this.$.divider.setContent(d); + this.$.divider.canGenerate = showd; + this.$.item.applyStyle("border-top", showd ? "none" : null); + } + }, + refreshList: function() { + if (this.filter) { + this.filtered = this.generateFilteredData(this.filter); + this.$.list.setCount(this.filtered.length); + } else { + this.$.list.setCount(this.db.length); + } + this.$.list.refresh(); + }, + addItem: function() { + var item = this.generateItem(enyo.cap(this.$.newContactInput.getValue())); + var i = 0; + for (var di; (di=this.db[i]); i++) { + if (di.name > item.name) { + this.db.splice(i, 0, item); + break; + } + } + // if we hit end of for-loop, add to end of list + if (!di) { + this.db.push(item); + } + this.refreshList(); + this.$.list.scrollToRow(i); + }, + removeItem: function(inIndex) { + this._removeItem(inIndex); + this.$.list.getSelection().remove(inIndex); + this.refreshList(); + }, + _removeItem: function(inIndex) { + var i = this.filter ? this.filtered[inIndex].dbIndex : inIndex; + this.db.splice(i, 1); + }, + removeTap: function(inSender, inEvent) { + this.removeItem(inEvent.index); + return true; + }, + removeSelected: function() { + // get selected items, sort numerically in decending order + var selected = enyo.keys(this.$.list.getSelection().getSelected()); + selected.sort(function(a,b) { return b-a; }); + // remove items one-by-one, starting with last in the list + for (var i=0; i < selected.length; i++) { + this._removeItem(selected[i]); + } + // clear selection, since all selected items are now gone + this.$.list.getSelection().clear(); + // re-render list in current position + this.refreshList(); + }, + populateList: function() { + this.$.popup.hide(); + this.createDb(~~this.$.countOutput.getContent()); + this.$.list.setCount(this.db.length); + this.$.list.setRowsPerPage(~~this.$.rowsPerPageOutput.getContent()); + // + this.hideDivider = this.$.hideDividerCheckbox.getValue(); + //this.$.divider.canGenerate = !this.hideDivider; + // + this.$.list.reset(); + }, + createDb: function(inCount) { + this.db = []; + for (var i=0; i b.name) return 1; + else return 0; + }); + }, + showSetupPopup: function() { + this.$.popup.show(); + }, + searchInputChange: function(inSender) { + enyo.job(this.id + ":search", enyo.bind(this, "filterList", inSender.getValue()), 200); + }, + filterList: function(inFilter) { + if (inFilter != this.filter) { + this.filter = inFilter; + this.filtered = this.generateFilteredData(inFilter); + this.$.list.setCount(this.filtered.length); + this.$.list.reset(); + } + }, + generateFilteredData: function(inFilter) { + var re = new RegExp("^" + inFilter, "i"); + var r = []; + for (var i=0, d; (d=this.db[i]); i++) { + if (d.name.match(re)) { + d.dbIndex = i; + r.push(d); + } + } + return r; + }, + countSliderChanging: function(inSender, inEvent){ + this.$.countOutput.setContent(Math.round(inSender.getValue()) * 50); + }, + rowsSliderChanging: function(inSender, inEvent){ + this.$.rowsPerPageOutput.setContent(Math.round(inSender.getValue()) * 5); + } +}); + +var avatars = [ + "angel.png", + "astrologer.png", + "athlete.png", + "baby.png", + "clown.png", + "devil.png", + "doctor.png", + "dude.png", + "dude2.png", + "dude3.png", + "dude4.png", + "dude5.png", + "dude6.png" +]; +var titles = [ + "Regional Data Producer", + "Internal Markets Administrator", + "Central Solutions Producer", + "Dynamic Program Executive", + "Direct Configuration Executive", + "International Marketing Assistant", + "District Research Consultant", + "Lead Intranet Coordinator", + "Central Accountability Director", + "Product Web Assistant" +]; + +// It's convenient to create a kind for the item we'll render in the contacts list. +enyo.kind({ + name: "ContactItem", + events: { + onRemove: "" + }, + published: { + importance: 0 + }, + components: [ + {name: "avatar", kind: "Image", classes: "list-sample-contacts-avatar"}, + {components: [ + {name: "name"}, + {name: "title", classes: "list-sample-contacts-description"}, + {content: "(415) 711-1234", classes: "list-sample-contacts-description"} + ]}, + {name: "remove", kind: "onyx.IconButton", classes: "list-sample-contacts-remove-button", src: "assets/remove-icon.png", ontap: "removeTap"} + ], + setContact: function(inContact) { + this.$.name.setContent(inContact.name); + this.$.avatar.setSrc(inContact.avatar); + this.$.title.setContent(inContact.title); + }, + setSelected: function(inSelected) { + this.addRemoveClass("list-sample-contacts-item-selected", inSelected); + this.$.remove.applyStyle("display", inSelected ? "inline-block" : "gne"); + }, + renderImportance: function() { + switch(this.importance) { + case 0: + this.$.importance.setContent("not important"); + break; + case -1: + this.$.importance.setContent("important"); + break; + case -2: + this.$.importance.setContent("very important"); + break; + default: + alert(this.importance+" - wowzer"); + break; + } + }, + removeTap: function(inSender, inEvent) { + this.doRemove(inEvent); + return true; + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListLanguagesSample.css b/lib/layout/list/samples/ListLanguagesSample.css new file mode 100644 index 0000000..d938ee6 --- /dev/null +++ b/lib/layout/list/samples/ListLanguagesSample.css @@ -0,0 +1,64 @@ +.list-sample-language { + color: white; +} +.list-sample-language-list { + background: url(assets/bg.png); +} +.list-sample-language-item { + height: 80px; + border-top: 1px solid #000; + padding: 12px 16px; + background-color: #333333; + position:relative; +} +.list-sample-language-list .rowNumberLabel { + position:absolute; + right:15px; + bottom: 10px; + font-size:12px; +} +.list-sample-language-list .itemLabel { + font-size:24px; + line-height:80px; + padding-left:30px; +} +.list-sample-language-list .serialLabel { + position:absolute; + right:80px; + bottom: 10px; + font-size:12px; +} +.list-sample-language-list .reorderDragger { + background:rgb(0,0,0); +} +.list-sample-language-list .swipeGreen { + background-color:rgb(0,160,40); +} +.list-sample-language-list h2 { + margin:0; + padding:0 0 0 20px; + font-size:24px; + line-height:100px; +} +.list-sample-language-list .dropButton { + width:90px; + height:60px; + position:absolute; + top:20px; + right:110px; +} +.list-sample-language-list .cancelButton { + width:90px; + height:60px; + position:absolute; + top:20px; + right:10px; +} +.list-sample-language-list .swipeTitle { + font-size:30px; + font-weight:bold; + text-align:center; + line-height:100px; + padding:0; + margin:0; +} diff --git a/lib/layout/list/samples/ListLanguagesSample.html b/lib/layout/list/samples/ListLanguagesSample.html new file mode 100644 index 0000000..74accc7 --- /dev/null +++ b/lib/layout/list/samples/ListLanguagesSample.html @@ -0,0 +1,23 @@ + + + + + Contacts List Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListLanguagesSample.js b/lib/layout/list/samples/ListLanguagesSample.js new file mode 100644 index 0000000..18ef39f --- /dev/null +++ b/lib/layout/list/samples/ListLanguagesSample.js @@ -0,0 +1,160 @@ +enyo.kind({ + name: "enyo.sample.ListLanguagesSample", + kind: "FittableRows", + classes: "list-sample-language enyo-fit", + data: [], + languages: { + English: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], + Italian: ["Uno", "Due", "Tre", "Quattro", "Cinque", "Sei", "Sette", "Otto", "Nove", "Dieci"], + Spanish: ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"], + German: ["Eins", "Zwei", "Drei", "Vier", "F\xFCnf", "Sechs", "Sieben", "Acht", "Neun", "Zehn"], + French: ["Un", "Deux", "Trois", "Quatre", "Cinq", "Six", "Sept", "Huit", "Neuf", "Dix"] + }, + components: [ + {kind: "onyx.MoreToolbar", layoutKind: "FittableColumnsLayout", style: "height: 55px;", components: [ + {content: "Rows:"}, + {kind: "onyx.InputDecorator", components: [ + {kind: "onyx.Input", value: "10", name: "numRows" } + ]}, + {kind: "onyx.Button", content: "Repopulate", ontap: "populateList"} + ]}, + {kind: "List", classes: "list-sample-language-list enyo-unselectable", + fit: true, multiSelect: true, + reorderable: true, centerReorderContainer: false, + enableSwipe: true, + onSetupItem: "setupItem", + onReorder: "listReorder", + onSetupReorderComponents: "setupReorderComponents", + // onSetupPinnedReorderComponents: "setupPinnedReorderComponents", + onSetupSwipeItem: "setupSwipeItem", + onSwipeComplete: "swipeComplete", + components: [ + {name: "item", classes: "list-sample-language-item", components: [ + {name: "text", classes: "itemLabel"}, + {name: "rowNumber", classes: "rowNumberLabel"}, + {name: "serial", classes: "serialLabel"} + ]} + ], + reorderComponents: [ + {name: "reorderContent", classes: "enyo-fit reorderDragger", components: [ + {name: "reorderTitle", tag: "h2", allowHtml: true} + ]} + ], + // For Enyo 2.2, we comment out these components to disable pinned mode which is still + // considered a work in progress. + /* pinnedReorderComponents: [ + {name: "pinnedReorderItem", classes: "enyo-fit swipeGreen", components: [ + {name: "pinnedReorderTitle", tag: "h2", allowHtml: true}, + {name: "dropButton", kind: "onyx.Button", ontap: "dropPinnedRow", content: "Drop", classes: "dropButton"}, + {name: "cancelButton", kind: "onyx.Button", ontap: "cancelPinnedMode", content: "Cancel", classes: "cancelButton"} + ]} + ], */ + swipeableComponents: [ + {name: "swipeItem", classes: "enyo-fit swipeGreen", components: [ + {name: "swipeTitle", classes: "swipeTitle"} + ]} + ] + } + ], + rendered: function() { + this.inherited(arguments); + this.populateList(); + }, + listReorder: function(inSender, inEvent) { + var movedItem = enyo.clone(this.data[inEvent.reorderFrom]); + this.data.splice(inEvent.reorderFrom,1); + this.data.splice((inEvent.reorderTo),0,movedItem); + }, + setupItem: function(inSender, inEvent) { + var i = inEvent.index; + if(!this.data[i]) { + return; + } + var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; + var val = this.data[i].val; + var number = this.languages[currentLanguage][val]; + var serial = this.data[i].serial; + this.$.rowNumber.setContent("ROW " + i); + this.$.text.setContent(number); + this.$.serial.setContent("#" + serial); + }, + setupReorderComponents: function(inSender, inEvent) { + var i = inEvent.index; + if(!this.data[i]) { + return; + } + var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; + var val = this.data[i].val; + var number = this.languages[currentLanguage][val]; + this.$.reorderTitle.setContent(number); + }, + /* setupPinnedReorderComponents: function(inSender, inEvent) { + var i = inEvent.index; + if(!this.data[i]) { + return; + } + var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; + var val = this.data[i].val; + var number = this.languages[currentLanguage][val]; + this.$.pinnedReorderTitle.setContent(number); + }, */ + //* Called when the "Drop" button is pressed on the pinned placeholder row + /* dropPinnedRow: function(inSender, inEvent) { + this.$.list.dropPinnedRow(inEvent); + }, */ + //* Called when the "Cancel" button is pressed on the pinned placeholder row + /* cancelPinnedMode: function(inSender, inEvent) { + this.$.list.cancelPinnedMode(inEvent); + }, */ + setupSwipeItem: function(inSender, inEvent) { + var i = inEvent.index; + if(!this.data[i]) { + return; + } + var newLang = (inEvent.xDirection == 1) + ? this.getNextLang(i) + : this.getPrevLang(i); + this.$.swipeTitle.setContent(this.data[i].langs[newLang]); + }, + swipeComplete: function(inSender, inEvent) { + var i = inEvent.index; + this.data[i].currentIndex = (inEvent.xDirection == 1) + ? this.getNextLang(i) + : this.getPrevLang(i); + this.$.list.renderRow(i); + }, + getNextLang: function(index) { + var currentLang = this.data[index].currentIndex; + return (currentLang + 1) % this.data[index].langs.length; + }, + getPrevLang: function(index) { + var currentLang = this.data[index].currentIndex; + return (currentLang - 1 + this.data[index].langs.length) % this.data[index].langs.length; + }, + populateList: function() { + this.createRandomData(); + this.$.list.setCount(this.data.length); + this.$.list.reset(); + }, + createRandomData: function() { + var languages = this.getLanguages(); + var langs; + var dataCount = parseInt(this.$.numRows.getValue(), 10); + this.data = []; + var sortFunc = function() {return 0.5 - Math.random();}; + for(var i=0;i + + + + Basic List Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListNoSelectSample.js b/lib/layout/list/samples/ListNoSelectSample.js new file mode 100644 index 0000000..0accadb --- /dev/null +++ b/lib/layout/list/samples/ListNoSelectSample.js @@ -0,0 +1,26 @@ +enyo.kind({ + name: "enyo.sample.ListNoSelectSample", + classes: "list-sample enyo-fit", + components: [ + {name: "list", kind: "List", count: 20000, noSelect: true, multiSelect: false, classes: "enyo-fit list-sample-list", + onSetupItem: "setupItem", components: [ + {name: "item", classes: "list-sample-item enyo-border-box", components: [ + {name: "index", classes: "list-sample-index"}, + {name: "name"} + ]} + ]} + ], + names: [], + setupItem: function(inSender, inEvent) { + // this is the row we're setting up + var i = inEvent.index; + // make some mock data if we have none for this row + if (!this.names[i]) { + this.names[i] = makeName(5, 10, '', ''); + } + var n = this.names[i]; + var ni = ("00000000" + i).slice(-7); + this.$.name.setContent(n); + this.$.index.setContent(ni); + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListOnyxItemSample.html b/lib/layout/list/samples/ListOnyxItemSample.html new file mode 100644 index 0000000..ee59493 --- /dev/null +++ b/lib/layout/list/samples/ListOnyxItemSample.html @@ -0,0 +1,23 @@ + + + + + Onyx.Item List Sample + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListOnyxItemSample.js b/lib/layout/list/samples/ListOnyxItemSample.js new file mode 100644 index 0000000..f56dae7 --- /dev/null +++ b/lib/layout/list/samples/ListOnyxItemSample.js @@ -0,0 +1,39 @@ +enyo.kind({ + name: "enyo.sample.ListOnyxItemSample", + classes: "list-sample enyo-fit", + components: [{ + name: "list", + kind: "List", + count: 20000, + multiSelect: false, + classes: "enyo-fit list-sample-list", + onSetupItem: "setupItem", + components: [{ + name: "item", + kind: "onyx.Item", + tapHighlight: true, + classes: "list-sample-item enyo-border-box", + components: [{ + name: "index", + classes: "list-sample-index" + }, { + name: "name" + }] + }] + }], + names: [], + setupItem: function (inSender, inEvent) { + // this is the row we're setting up + var i = inEvent.index; + // make some mock data if we have none for this row + if (!this.names[i]) { + this.names[i] = makeName(5, 10, '', ''); + } + var n = this.names[i]; + var ni = ("00000000" + i).slice(-7); + // apply selection style if inSender (the list) indicates that this row is selected. + this.$.item.addRemoveClass("list-sample-selected", (i % 2 === 0)); + this.$.name.setContent(n); + this.$.index.setContent(ni); + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.css b/lib/layout/list/samples/ListPulldownSample.css new file mode 100644 index 0000000..1bdf4cf --- /dev/null +++ b/lib/layout/list/samples/ListPulldownSample.css @@ -0,0 +1,15 @@ +a:link, a:visited { + color: lightblue; + text-decoration: underline; +} +.list-sample-pulldown-list { + background: grey; +} +.list-sample-pulldown-item { + border-bottom: 1px solid #0E0E0E; + padding: 12px 16px; + background-color: #333333; + /**/ + font-size: 14px; + color: white; +} \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.html b/lib/layout/list/samples/ListPulldownSample.html new file mode 100644 index 0000000..9574964 --- /dev/null +++ b/lib/layout/list/samples/ListPulldownSample.html @@ -0,0 +1,22 @@ + + + + + Pulldown List Sample + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.js b/lib/layout/list/samples/ListPulldownSample.js new file mode 100644 index 0000000..5e2fd26 --- /dev/null +++ b/lib/layout/list/samples/ListPulldownSample.js @@ -0,0 +1,97 @@ +enyo.kind({ + name: "enyo.sample.ListPulldownSample", + classes: "enyo-unselectable enyo-fit onyx", + kind: "FittableRows", + components: [ + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.InputDecorator", components: [ + {name: "searchInput", kind: "onyx.Input", value: "enyojs", placeholder: "Enter seach term"}, + {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px;"} + ]}, + {kind: "onyx.Button", content: "search", ontap: "search"} + ]}, + {name: "list", kind: "PulldownList", classes: "list-sample-pulldown-list", fit: true, onSetupItem: "setupItem", onPullRelease: "pullRelease", onPullComplete: "pullComplete", components: [ + {style: "padding: 10px;", classes: "list-sample-pulldown-item enyo-border-box", components: [ + {name: "icon", kind: "Image", style: "float: left; width: 48px; height: 48px; padding: 0 10px 10px 0;"}, + {name: "name", tag: "span", style: "font-weight: bold;"}, + {name: "handle", tag: "span", style: "color: lightgrey;"}, + {name: "date", tag: "span", style: "float: right; color: lightgrey;"}, + {tag: "br"}, + {name: "text", tag: "p", style: "word-wrap: break-word;", allowHtml: true} + ]} + ]} + ], + rendered: function() { + this.inherited(arguments); + this.search(); + }, + pullRelease: function() { + this.pulled = true; + // add 1 second delay so we can see the loading message + setTimeout(enyo.bind(this, function() { + this.search(); + }), 1000); + }, + pullComplete: function() { + this.pulled = false; + this.$.list.reset(); + }, + search: function() { + // Capture searchText and strip any whitespace + var searchText = this.$.searchInput.getValue().replace(/^\s+|\s+$/g, ''); + + if (searchText !== "") { + var req = new enyo.JsonpRequest({ + url: "http://search.twitter.com/search.json", + callbackName: "callback" + }); + req.response(enyo.bind(this, "processSearchResults")); + req.go({q: searchText, rpp: 20}); + } else { + // For whitespace searches, set new content value in order to display placeholder + this.$.searchInput.setValue(searchText); + } + }, + processSearchResults: function(inRequest, inResponse) { + this.results = inResponse.results; + this.$.list.setCount(this.results.length); + if (this.pulled) { + this.$.list.completePull(); + } else { + this.$.list.reset(); + } + }, + setupItem: function(inSender, inEvent) { + var i = inEvent.index; + var item = this.results[i]; + this.$.icon.setSrc(item.profile_image_url); + this.$.name.setContent(item.from_user_name); + this.$.handle.setContent(" @" + item.from_user); + this.$.date.setContent(this.getRelativeDateString(item.created_at)); + this.$.text.setContent(this.parseTweet(item.text)); + }, + getRelativeDateString: function(inDateString) { + var d = new Date(inDateString); + var td = new Date(); + var s; + if (td.toLocaleDateString() == d.toLocaleDateString()) { + var dh = td.getHours() - d.getHours(); + var dm = td.getMinutes() - d.getMinutes(); + s = dh ? dh + " hour" : (dm ? dm + " minute" : td.getSeconds() - d.getSeconds() + " second"); + } else { + var dmo = td.getMonth() - d.getMonth(); + s = dmo ? dmo + " month" : td.getDate() - d.getDate() + " day"; + } + return s.split(" ")[0] > 1 ? s + "s" : s; + }, + parseTweet: function(inText) { + var t = inText; + t = t.replace(/[A-Za-z]+:\/\/[A-Za-z0-9_-]+\.[A-Za-z0-9_:%&~\?\/.=-]+/g, function(url) { + return "" + url + ""; + }); + return t.replace(/[@]+[A-Za-z0-9_-]+/, function(u) { + var username = u.replace("@", ""); + return "@" + username + ""; + }); + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/NameGenerator.js b/lib/layout/list/samples/NameGenerator.js new file mode 100644 index 0000000..647d102 --- /dev/null +++ b/lib/layout/list/samples/NameGenerator.js @@ -0,0 +1,48 @@ +// Licensed under Creative Commons Attribution 3.0 License +// attributed to: http://leapon.net/en/random-name-generator-javascript +function rnd(minv, maxv) { + if (maxv < minv) return 0; + return Math.floor(Math.random()*(maxv-minv+1)) + minv; +} + +function makeName(minlength, maxlength, prefix, suffix) { + prefix = prefix || ''; + suffix = suffix || ''; + // these weird character sets are intended to cope with the nature of English (e.g. char 'x' pops up less frequently than char 's') + // note: 'h' appears as consonants and vocals + var vocals = 'aeiouyh' + 'aeiou' + 'aeiou'; + var cons = 'bcdfghjklmnpqrstvwxz' + 'bcdfgjklmnprstvw' + 'bcdfgjklmnprst'; + var allchars = vocals + cons; + var length = rnd(minlength, maxlength) - prefix.length - suffix.length; + if (length < 1) length = 1; + var consnum = 0; + var i; + if (prefix.length > 0) { + for (i = 0; i < prefix.length; i++) { + if (consnum == 2) consnum = 0; + if (cons.indexOf(prefix[i]) != -1) { + consnum++; + } + } + } + else { + consnum = 1; + } + var name = prefix; + for (i = 0; i < length; i++) + { + //if we have used 2 consonants, the next char must be vocal. + if (consnum == 2) + { + touse = vocals; + consnum = 0; + } + else touse = allchars; + //pick a random character from the set we are goin to use. + c = touse.charAt(rnd(0, touse.length - 1)); + name = name + c; + if (cons.indexOf(c) != -1) consnum++; + } + name = name.charAt(0).toUpperCase() + name.substring(1, name.length) + suffix; + return name; +} \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.css b/lib/layout/list/samples/PersistentSwipeableItemSample.css new file mode 100644 index 0000000..7d5990b --- /dev/null +++ b/lib/layout/list/samples/PersistentSwipeableItemSample.css @@ -0,0 +1,42 @@ +.list-sample-persistent-swipeable-item { + color: white; +} +.list-sample-persistent-swipeable-item-list { + background: url(assets/bg.png); +} +.list-sample-persistent-swipeable-item-item { + height: 80px; + border-top: 1px solid #000; + padding: 12px 16px; + background-color:rgba(0,0,0,0.5); +} +.list-sample-contacts-item > * { + display: inline-block; + vertical-align: middle; +} +.list-sample-persistent-swipeable-item-list .itemLabel { + float:left; + font-size:24px; + line-height:80px; + padding-left:20px; +} +.list-sample-persistent-swipeable-item-list .swipeGreen { + background-color:rgba(0,160,40,0.8); +} +.list-sample-persistent-swipeable-item-list .swipeRed { + background-color:rgba(160,0,40,0.8); +} +.list-sample-persistent-swipeable-item-list h2 { + margin:0px; + padding:0px 0px 0px 20px; + font-size:24px; + line-height:100px; +} +.list-sample-persistent-swipeable-item-list .swipeTitle { + font-size:30px; + font-weight:bold; + text-align:center; + line-height:100px; + padding:0px; + margin:0px; +} \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.html b/lib/layout/list/samples/PersistentSwipeableItemSample.html new file mode 100644 index 0000000..c981ab6 --- /dev/null +++ b/lib/layout/list/samples/PersistentSwipeableItemSample.html @@ -0,0 +1,21 @@ + + + + + Persistent Swipeable Item Sample + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.js b/lib/layout/list/samples/PersistentSwipeableItemSample.js new file mode 100644 index 0000000..d10c85b --- /dev/null +++ b/lib/layout/list/samples/PersistentSwipeableItemSample.js @@ -0,0 +1,60 @@ +enyo.kind({ + name: "enyo.sample.PersistentSwipeableItemSample", + kind: "FittableRows", + classes: "list-sample-persistent-swipeable-item enyo-fit", + data: ["Cat","Dog","Hippopotamus"], + components: [ + {kind: "List", classes: "list-sample-persistent-swipeable-item-list enyo-unselectable", + fit: true, multiSelect: true, reorderable: false, enableSwipe: true, centerReorderContainer: false, + onSetupItem: "setupItem", + onSetupSwipeItem: "setupSwipeItem", + onSwipeComplete: "swipeComplete", + components: [ + {name: "item", classes: "list-sample-persistent-swipeable-item-item", components: [ + {name: "text", classes: "itemLabel", allowHtml: true} + ]} + ], + swipeableComponents: [ + {name: "swipeItem", classes: "enyo-fit swipeGreen", components: [ + {name: "swipeTitle", classes: "swipeTitle", content: "This is a test"} + ]} + ] + } + ], + rendered: function() { + this.inherited(arguments); + this.populateList(); + }, + populateList: function() { + this.$.list.setCount(this.data.length); + this.$.list.reset(); + }, + setupItem: function(inSender, inEvent) { + if(!this.data[inEvent.index]) { + return; + } + + this.$.text.setContent(this.data[inEvent.index]); + }, + setupSwipeItem: function(inSender, inEvent) { + if(!this.data[inEvent.index]) { + return; + } + + if(inEvent.xDirection === -1) { + // Persist swipeable item if swiped from right to left + this.$.list.setPersistSwipeableItem(true); + this.$.swipeTitle.setContent("This is a persistent item"); + this.$.swipeItem.removeClass("swipeGreen"); + this.$.swipeItem.addClass("swipeRed"); + } else { + // Don't persist swipeable item if swiped from left to right + this.$.list.setPersistSwipeableItem(false); + this.$.swipeTitle.setContent("This is not a persistent item"); + this.$.swipeItem.removeClass("swipeRed"); + this.$.swipeItem.addClass("swipeGreen"); + } + }, + swipeComplete: function(inSender, inEvent) { + } +}); \ No newline at end of file diff --git a/lib/layout/list/samples/assets/avatars/angel.png b/lib/layout/list/samples/assets/avatars/angel.png new file mode 100644 index 0000000000000000000000000000000000000000..d67d1b76e5d7eeb05d68942f5078a19e3ab35269 GIT binary patch literal 2476 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 U7eILG4FCWD07*qoM6N<$f@m=ZtN;K2 literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/athlete.png b/lib/layout/list/samples/assets/avatars/athlete.png new file mode 100644 index 0000000000000000000000000000000000000000..8579266ac48d958f1aa035db2351959081f3203f GIT binary patch literal 2070 zcmV+x2 zkl+veK#U*2pMnrVLV^m7ipzkFn|ez}*M+4E$=YU3(p>Gvc8+78`;GTFUe(bX&GJQ$ zY@f^bJ@4~g!{9FKb06Qm6Fm3j0KCJJ$nSI=kF9Q~#k!)MG%e@o-~Tm#;%yy_LMRi8gSQTYB=32?W%I66AY zCtCSG?HS4*d2qCs>u8H3B#Gby0Wb^$$8j6aWjkU_GTHLz{r9!ak54XN*fs)t`laXZ z@6UX3WFX5#A|b?M5yYZl1UQyd@L=06y1QD@n`=i$I?PVZ6dxW*3qPKim+gBcz~0I& zuH}4nM|YB8Sq_50BODfyNJJo!3PFKGe{VY?;UHwWj#^DeGA^c+VEDjR6bRfT|Dk-W zH5kmua*YDSBe`v8dv~V*)ByO%P@Yr5nKzd=g@bjLCkY3v}N+x zHyp-0^Ya*=UU3}HJhv?h{QAV@lJ3~1N9pF-20^9sNnN`Rm%dwO9X;(KYJ9O4Nt(%(B55D!}!F*rO&vvz>dN=-jhN;CFRIaVTP*vE5iA+~J z!l3{-&O?przz*3&b+SC1rP6f)-ih}`;KlDednA)dAOGy*eL45JpEF$t_n`mqM-Y)h zh{ogS&gYRzr^q!5EOHGmQHibx;hmjjxNjWVKe{XX`?2w>*S6$>@4oO%XDllI~xu-t~fg-*ol|oy42h9ZJYLRZD|ADUP+U1K-UOJD&(}$szsuXA(bZR^rxxlh0BWM^2N=XDGvBrQ>8=HZc zizDCNiBBCG=p%Bco_+E|yY88Q2V-|CZlHAhBw{@&q#hii-Y-B^YUFQ@qMzSPK^jI} z&jw2Y$ev$Bd2tP?149V#0)~eN@x;eQx}#CyA;j`jM0%CjRjCryh#l zjllIvD6&eQ=PKZf6$o4um*y%6Q9tml2OA(YcpA%sjp>NAhy3kdp)x%WW+aLHhljxG z6bYfO#{7`Zwqj(k+&Ok${RC}&tify(wsdEM3ysYR-DXWl?xp$zVU9L&0b z!1Mx)*(JDipTdC#5_&sNH9;+7Woa3qSb|Cs+bG$3y@Y7UAK~3z+B!p^r{PabN)!I_ z`-gpCbSJpxNA5ZU$PSd7XISEy7GQ^6$9*3k%+FUOXthCIA2c07*qoM6N<$g7QYz A+W-In literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/baby.png b/lib/layout/list/samples/assets/avatars/baby.png new file mode 100644 index 0000000000000000000000000000000000000000..018e8152fca4b3ec39843a65825a39c129ff0fad GIT binary patch literal 1756 zcmV<21|#{2P)E;$u-evP*jYFtXgSlp(2(#U6{_4**bIg>$$fWi4RjK#uq)w$$#(s_y5oL zpYxq_{sI1%|GMy3yWok3TH_nnrH8uPRGd6>@yNdpU`=nTr?WNu4Ce@Uq+3GERxeAO z9vqpOUMK)|H6L%gcf|%~8E@RymtMsj9+TM`&Sgq&zGxhWEABOn(!1~N%gp@a0G@ns zO^;#WRaF&kUD6R^v8af0$)0l|&q3F1j7}7B=G;tqwyN)`a2IwTH~{M(0r2qMy_=P= z@X`9!X|+KWp%D_(GN2naEq47a9M^?qS*X@DjEolWYo_ugS7BQ}IWbY4Z~wX+cyvow z8z0~gY`&o*nr>-ANC_dTMxe++1Qi7ey$2)-qQHYO=7UMZBm_j(m8;dd&iq#S;F~7lAx32Z(6+InD#1l}0Aw<*|8saI$8yBIWAqiDgAqXO>RSlBBf!u+(D$%>s+tm{O zZt&OQZ}n^l^(Nyn>8_rRMsR{eDuU-kNOA;B3{mVwIxmB58w4Uw->MiM9tJ1N6ds1< zoiX-ZVQM>V^YwxO1Z61&CO{Hp@E!m$3{h5T4AIXrF@S-yG=G%k8roCMI5(C-KoF3O zQiw$9`uRdo7l39sS)S*cd6A3@0SEyZoCih<(io(;i?EGZIJOCJ5?sa+SOJW};4l}m z#D(Sqz|{qyIYYKfpK#=C@`S)sD9H638R94$j3Z;-9LM|bw(TGyi*zaiK+iSZnzul4 z^=G+~laV3#m^tv zab56KHI3$_+b}+I5QY2Ra3b29G#qEbqgy?|d4*_#YbJYMC$8A~GtzvL8f;G3?f+HgZ^mRv(4J@H6fYESwXF4p?k5!#UlI;+KN&c z3DPL3a(U?M0=SU3r^lxZl&lz)UGfN3WP@CupEWR5)KSrOjO8oP92xhwzE730M&Iau zVKOOQlW`ugm~<0ul_qT>RY~P52Jrio)A!DYV<*mzj8QWp-`S3@CaK{)6PU$`2!gXi z*uH)k(*(wKnco$?>zNz~pg9@zj3-GWmqPA^z`P;=AAUA@{*^Z;HVlraCkF;b5Dv=J zk~t`J^=c);^|nOOe|{QIEqx6&lc$<6*R;ImB~$ED=|(64!TV7nt&rwO%a=&$%a!~w zajPc2J#^&wJ=tP4qC^_t(iLr@XkvV72s=A>V{JEwQlU!h7wMuZ`Chn?v+?D(lkV}s z$``|DwYO=X)1;-#jr(A)0Dv#88#gMl(y~*QBlpSC#!lNTb9bgbW|E@FbYEa19n_$> y(Cw)*oiirNW#icBcy;gogT+I%y!Lm)f65=+DCt%HzI_Y;0000Ub^EeVOqoHz-I?Igx_ocI#oeSD7herMia&J zS=UnbS~$3eJ#hN;>2F4((cf&^w8_%k+zho^jY6Ry8?D3XbfTxHr!YT1|HBIxE}WrP zipv3@__QDCR4?mvx-*9lA1W1my06vE*!^m;uv?e}kMXl}kZHar~tTmVkB zwtg+?^S$})tZ&&=2$+Trv0kk98qdO%UF=I45P8aD(2SB8N6X9Dmu zhvQoYwff?-k3Vj9Su9YJGolz*uU^H?n>W$Y(juRnIh~rCf+&g*$Pxsg{?;wD4G*^_ zIqnHZE_Z=Ih|31Bzpn11r;J9u-)_guiWP`QA~MD7q>P2$-d=3kvIR3UGZ09K0=*+l zPQuaEg^j@=tQrlX$z=URIxVpADbm!lA(|5U z_5S-sT9=3&+vUsHc;g1FW-~Ix!aPOBd@P2cY}PPJI(`@ce&GVq``$PStZm&o`FkyG zym|9xIkuSa*y+>hG&E&p(2bA7OwJP~6Jj0@QnRy&kSL8zC%}d;0;-1rP%d1ki$-7X zGnsbQ0G+{O$B=Nj5Dx^f^89(2>gr&#+2n}e$dqf=AVRY=Ix1g9lun){0JCI@B{+W| z1J8#-sWOiHzSixAO|OT69DsDt`{Ij86U9vJMxzlT-9JzB$e}}+tgS_ybTZ56PbA>X z<&XxB_d&+BJOFIuBx#nX4dVj?$j~ejh&+jIVq!whfD8ni)8tG?tVDM2#@*^_xanCZ zoqie!(8j;~OboE0Pb9=HhXbLJ5ya?TQ=t&BXOFDd`vEXbXelywkU(#4*ih(|q*Ein zG15!thmuGKMiL$fv#N?GL0MT5%YZr_orw;}2bxI(|d4AZxawR%mdkskvmzuI*o*YvplmR4@N!+`44+et)@pv3| zyIr?j=ZgYhgOj8o=9r@s>nY?I-7EoTG8x%(H&gL(usH8sg=2M!$I_U_$#khI}Gdh}@J z=LYcV$B{3c8XT3HnjG-^{cuxQvM87(Q8E@BB+^}^3s#s|Rve&+VPLo-%BdQ*FBQN8 ztKsG!Ke9&M4UONbt-VB9K$0dA1V|H@jJQity|AztF znjUL5Sqr{+2fneDFjz0c*S`%W^V^sj*pA=&ZzEbw={c|)HIIIPq~-;zZ<&X>@jCpj z6KL7~HcXXP=*+FK*5zonZ`ZeUuBEL_WGq=}N(bj21i(>NKCPYe*^!D!NMxN<V|^x3^-2p%0PyK4jgU5XxVL_s;Vu(}iGbs6thf62^+vFqEgEGF0*k zW$`QQY-APp0Z}s$3jyp5-fEggdKmX6EJ%yj5FB$rq3p(tPfI`w;MCULa)83~&X(50R#oEbew|GvR8lI36ZtC$&;FMm(f+p~qF(iYv zNTt0*|0tDfGYOEc##x0->?-0j1%&Pbsl)_b-7J|v9a5P32E_{6TVJ|&)}&;~at{K) z#w^)e!er0IP&WpXLy@9_qYgM@gT@#^HerLH^gv8o$x(s+3wRLmSs)}lbVXF6y(uK4 z(*!t#=oIx2(Ywe5G}NIZQ`(!^d+|BU9T3mweeD@2N!U9~bD zq%4#=s*14&SR8!_4m|;#c941n9&vvSbhcXv57j{kdytQMJmQr9b-KTQ(7ux_)v%NQ z$I-+7oHBs5WRFlMx>jpPhrl&7s4LQysxn1+KIhO{R}HHJgWHN)MQ^Gokqpv}D(f1j zBIaw!784Pt7@mHE-oHjRcfaGM0$7+cbR{uWl@x6(#dV=Xt5n*PS(40MqI}V!^e+u8 V2=&|Whywrs002ovPDHLkV1nzTI_v-d literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/devil.png b/lib/layout/list/samples/assets/avatars/devil.png new file mode 100644 index 0000000000000000000000000000000000000000..0b2bfff7a3ca1762e71a3dc3bd8d1f56a82aaccb GIT binary patch literal 2236 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 KMNUMnLSTaSV-W}d literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/dude.png b/lib/layout/list/samples/assets/avatars/dude.png new file mode 100644 index 0000000000000000000000000000000000000000..caf0b64070826e184ce79ed57b1183ee2d44f7fd GIT binary patch literal 2196 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 literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/dude5.png b/lib/layout/list/samples/assets/avatars/dude5.png new file mode 100644 index 0000000000000000000000000000000000000000..c299afdf6125a9383cac6625019ad749deec3492 GIT binary patch literal 2065 zcmV+s2=4cZP)75?VEJG<+B`jOa9Qa5QUx3T56DWXzQDHT#mOeI7@k&uueO2rQlQl(0W z9|ZnZA}DHv6pHv)q>3M)(g2B))`k`lR2OI}Drz@=W!GNsd*?lKXE=AfhO{K9O)~b; z?A*C~&v(xG&SM39!gc)k@ewVV`tJO~{IsI#cb7_e(Xp+@_`Uc1MG%BvF~)v*^5jY9 zlg_!>CEV)ev9EsZSURo06pBhlN+gj@r%941^kpDRB3fMou4yc^O!L@JUU*^d{{bN0 z?8V_DN2Y=3<+kl*{4jzn%TPoCk|@%bBCs$-z1f5t;ci6`&Yw7OV$U4|(Es@3Y2RmO z?I4t*D1s46o zk^oVls1c};yh1kweu%Yto%ST2zLiI}4PbhDTF+)P&j;jUiCdgVAe~O3zmUaXA&*o_ zM?_)ZAu%lrEMn+%I$%OnIC}JGai;*}k1tq^ja1e*R6&qp>t#uS#H}WadF*Y+fnnJ& zJr9=aLXl*6f)CR);Yzgmb^$cknqfDUKqi|bOX)mvy~x4HA~>ip^2zEDhGC#zG1c66l!!et%yBlz6|Am#@wfJq(TH}3##rU`0Vdx?62yi)-G^MzBV zPK||u|8=MFHUiIrBCB951f$#+NL;52QPvQ+HaeyYDK|<*NW@Rip1n5r*UQ0e0XTj7 zbibO=W(6fR{BF%6if|SZx|T$-3F#ifcLR#Qk3D1e;gLof7tWu9ZCS6}b_iC> z<*#^tIP6evTaJs%^DczQMd*9P2Zso0qE@ZppI6?8KK?8Uli$H>=Y9*3JX7p1mG&P# ztnCzlbp6A>DwW3UrJ1o0-hc1Fo_%A&LfOV{aS@i$K)u>PtKI46{=P~TW5i)+vn8O?AP3KQSJM#abXzW+m7ugB0u;>N(h0ES0KsXK1Y2YrQs zVz*iQ!=s;h;)`$1Ub?jH5KK)>J)@^H-xgI};7y2k!7d$G8X7`AqvM0c4ZL{fXRu5o z?vi{q&}ffBT`^lIAel@;Cvk{7S}LuELGY!);h|So78k4A@_@sVoYpf8_`l~a3!=lLWac|wHIYGC}H{g}9a zoWesM(vqK>nE2Glwg3by9PvFjo^}{jIc_;U(1rl3D-{BxB9%!~>!mv2Z31Kgi)X|V zg}^ep7#$hGRr1v8wQ@W&iqyj+Iecnc03`A)pZ|EZW4#u;b$3ajN&o`#Oz5*7Ko(EN zg(#JH3*5jOTLjdho)09L$eA4VkuH|5OuaC%L zK7?|XbER9#X$KNoBA$dg?G~D?77Y4qk#d8$!oyM;>_^1Hhv@hcNuDG_lDwXK{{hf# zcV=spdNSodFTA24#uaW8L=;=U=@AyM@pqK(Xi=twAw#>}CgpZKvN^5;m&iO&>Zfc{ zIR|!=^poUBQrCIozep^r`&@Ztd7M&g-{8>hcH~5>^La>Qk?F?)4J|5VCC`86*lxqN%=vb!K0~46P3dnWYrNciT)}oHd9laf;U1&& vJtlK<*uD4pUW)Oxde7nyNm{+N8(#kgD9-PG+F1#^00000NkvXXu0mjf#HQtt literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/avatars/dude6.png b/lib/layout/list/samples/assets/avatars/dude6.png new file mode 100644 index 0000000000000000000000000000000000000000..3ed55360e2fa99462f30b433724b835a5773423d GIT binary patch literal 2063 zcmV+q2=MobP)=}C=9y^JXv`uIVG>rt2LO}(TRuw4{_wJBaR|I&SWXUM^^^~)BT0>e(iO7JGhg*{v-|NVQBUQn?-G>?I)Vayg)f#r>oP-8z33-X9R%~}G{oPk47;H+QWe<-UNij0T) zc7u<_aBAdrSP2eC65#j}K3WuD5&7bz3E|C2%XWhe7^u%R+g@(=fV$k>8+6NBpm6M7 zzX#_|55UeXqiahR;4*v;jLy#@C346%haHy@bQ-!`b{=3rf3y9?W)G~J@_O=;hc6nB z;N@3OK-z2}m5M_XCCHStQm>#vMCt|*Hv;Hc8A4wQLQlNZiUds=Xq!ntmL8Sy#>JPR z_azCj1WAxlcTH3&D&tk;M;Jc0s-VrG|Hn8^Z5A;;E%e?M0D8jM*e+%;o35an==OXY zHOI#CVhvqqIUb(xgsLd;z!CU9YBLVDy}tl2@17gG8vqPl4>}7S;E5^J=48}XOe|fR z#FjI0?7FuPeq2Bxa0pzyA*ezenF5M~Zso23=;%ye{r(e2&~R(`b4?5Qy(~d`0zE$ZalUBo8OLY+rAYOQ{yO>dJwEk zqAjjKk|athfCqjA#I=0eLv*}j$ZHa+!9XodHUCxCcJ7&$cufBus+7;wf4-K;cM%puM0q5r-rR4X99mfq?vT%JEmL?yIdH?0*6{bRhN9 z_N4s$6OV6{ySq~;U!TG0t1e2La>!?Fl*b#;5@fw(LJGCuHIUO{_-&ckPh+Lhfa?V4C<0&jhKsJOfK^M! zm61j;HdgOvzIE{UugXhz4B+rVb+e|#E`D$SdhH)H?;A8{drNVM0?|wZs4XQyizQ*# z6SNHT%9UwBI@R`x;b-dDFeosnI?mm7T{Ej4Gmi)7w4;tFls|zR=D!QfoWu=Z zU~BP-LEWwmMI(;A>6Cy%&OoWu0bSRjs48MANuVmwC~-UuUGjY~z|hbN9(5;c{dJD06fQq$9S-oIFw+KqVZn^cS~OiSg)x8 zZDf+y(|xa2p>~_6#8sq{an$P;9LquA*;w%J!|Bf_;l(%5MTPo8N}#9~aoHmIfQn+)V#%i%^S+xggZqb6Aqb*+>9RwHi=zr_Op|cm*)AY~3QkNbdwfZo=%DK*=<-}3uXpqE?vild6SP1zBxEM zdF{~I{>5kMnp|&|9Qc%3u60Jy*Acr+m`?U002ovPDHLkV1n!C*NXrE literal 0 HcmV?d00001 diff --git a/lib/layout/list/samples/assets/bg.png b/lib/layout/list/samples/assets/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..61c031f5cec933d6e13cd6aa3ed851b51015fe6f GIT binary patch literal 79561 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

    [^\r]+?<\/pre>)/gm, function(e, t) {
    -var n = t;
    -return n = n.replace(/^  /mg, "~0"), n = n.replace(/~0/g, ""), n;
    -}), y("
    \n" + n + "\n
    "); -}), e; -}, x = function(e) { -e = e.replace(/^\n+/g, ""), e = e.replace(/\n+$/g, ""); -var t = e.split(/\n{2,}/g), r = new Array, i = t.length; -for (var s = 0; s < i; s++) { -var o = t[s]; -o.search(/~K(\d+)K/g) >= 0 ? r.push(o) : o.search(/\S/) >= 0 && (o = a(o), o = o.replace(/^([ \t]*)/g, "

    "), o += "

    ", r.push(o)); -} -i = r.length; -for (var s = 0; s < i; s++) while (r[s].search(/~K(\d+)K/) >= 0) { -var u = n[RegExp.$1]; -u = u.replace(/\$/g, "$$$$"), r[s] = r[s].replace(/~K\d+K/, u); -} -return r.join("\n\n"); -}, T = function(e) { -return e = e.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&"), e = e.replace(/<(?![a-z\/?\$!])/gi, "<"), e; -}, N = function(e) { -return e = e.replace(/\\(\\)/g, _), e = e.replace(/\\([`*_{}\[\]()>#+-.!])/g, _), e; -}, C = function(e) { -return e = e.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '
    $1'), e = e.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, function(e, t) { -return k(L(t)); -}), e; -}, k = function(e) { -function t(e) { -var t = "0123456789ABCDEF", n = e.charCodeAt(0); -return t.charAt(n >> 4) + t.charAt(n & 15); -} -var n = [ function(e) { -return "&#" + e.charCodeAt(0) + ";"; -}, function(e) { -return "&#x" + t(e) + ";"; -}, function(e) { -return e; -} ]; -return e = "mailto:" + e, e = e.replace(/./g, function(e) { -if (e == "@") e = n[Math.floor(Math.random() * 2)](e); else if (e != ":") { -var t = Math.random(); -e = t > .9 ? n[2](e) : t > .45 ? n[1](e) : n[0](e); -} -return e; -}), e = '' + e + "", e = e.replace(/">.+:/g, '">'), e; -}, L = function(e) { -return e = e.replace(/~E(\d+)E/g, function(e, t) { -var n = parseInt(t); -return String.fromCharCode(n); -}), e; -}, A = function(e) { -return e = e.replace(/^(\t|[ ]{1,4})/gm, "~0"), e = e.replace(/~0/g, ""), e; -}, O = function(e) { -return e = e.replace(/\t(?=\t)/g, " "), e = e.replace(/\t/g, "~A~B"), e = e.replace(/~B(.+?)~A/g, function(e, t, n) { -var r = t, i = 4 - r.length % 4; -for (var s = 0; s < i; s++) r += " "; -return r; -}), e = e.replace(/~A/g, " "), e = e.replace(/~B/g, ""), e; -}, M = function(e, t, n) { -var r = "([" + t.replace(/([\[\]\\])/g, "\\$1") + "])"; -n && (r = "\\\\" + r); -var i = new RegExp(r, "g"); -return e = e.replace(i, _), e; -}, _ = function(e, t) { -var n = t.charCodeAt(0); -return "~E" + n + "E"; -}; -}; - -// foss/syntaxhighlighter_3.0.83_fork/sh-min.js - -var XRegExp; - -if (XRegExp) throw Error("can't load XRegExp twice in the same frame"); - -(function() { -function e(e, n) { -if (!XRegExp.isRegExp(e)) throw TypeError("type RegExp expected"); -var r = e._xregexp; -return e = XRegExp(e.source, t(e) + (n || "")), r && (e._xregexp = { -source: r.source, -captureNames: r.captureNames ? r.captureNames.slice(0) : null -}), e; -} -function t(e) { -return (e.global ? "g" : "") + (e.ignoreCase ? "i" : "") + (e.multiline ? "m" : "") + (e.extended ? "x" : "") + (e.sticky ? "y" : ""); -} -function n(e, t, n, r) { -var i = a.length, s, o, f; -u = !0; -try { -while (i--) { -f = a[i]; -if (n & f.scope && (!f.trigger || f.trigger.call(r))) { -f.pattern.lastIndex = t, o = f.pattern.exec(e); -if (o && o.index === t) { -s = { -output: f.handler.call(r, o, n), -match: o -}; -break; -} -} -} -} catch (l) { -throw l; -} finally { -u = !1; -} -return s; -} -function r(e, t, n) { -if (Array.prototype.indexOf) return e.indexOf(t, n); -for (var r = n || 0; r < e.length; r++) if (e[r] === t) return r; -return -1; -} -XRegExp = function(t, r) { -var i = [], o = XRegExp.OUTSIDE_CLASS, a = 0, l, c, h, p, v; -if (XRegExp.isRegExp(t)) { -if (r !== undefined) throw TypeError("can't supply flags when constructing one RegExp from another"); -return e(t); -} -if (u) throw Error("can't call the XRegExp constructor within token definition functions"); -r = r || "", l = { -hasNamedCapture: !1, -captureNames: [], -hasFlag: function(e) { -return r.indexOf(e) > -1; -}, -setFlag: function(e) { -r += e; -} -}; -while (a < t.length) c = n(t, a, o, l), c ? (i.push(c.output), a += c.match[0].length || 1) : (h = f.exec.call(d[o], t.slice(a))) ? (i.push(h[0]), a += h[0].length) : (p = t.charAt(a), p === "[" ? o = XRegExp.INSIDE_CLASS : p === "]" && (o = XRegExp.OUTSIDE_CLASS), i.push(p), a++); -return v = RegExp(i.join(""), f.replace.call(r, s, "")), v._xregexp = { -source: t, -captureNames: l.hasNamedCapture ? l.captureNames : null -}, v; -}, XRegExp.version = "1.5.0", XRegExp.INSIDE_CLASS = 1, XRegExp.OUTSIDE_CLASS = 2; -var i = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g, s = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, o = /^(?:[?*+]|{\d+(?:,\d*)?})\??/, u = !1, a = [], f = { -exec: RegExp.prototype.exec, -test: RegExp.prototype.test, -match: String.prototype.match, -replace: String.prototype.replace, -split: String.prototype.split -}, l = f.exec.call(/()??/, "")[1] === undefined, c = function() { -var e = /^/g; -return f.test.call(e, ""), !e.lastIndex; -}(), h = function() { -var e = /x/g; -return f.replace.call("x", e, ""), !e.lastIndex; -}(), p = RegExp.prototype.sticky !== undefined, d = {}; -d[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/, d[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/, XRegExp.addToken = function(t, n, r, i) { -a.push({ -pattern: e(t, "g" + (p ? "y" : "")), -handler: n, -scope: r || XRegExp.OUTSIDE_CLASS, -trigger: i || null -}); -}, XRegExp.cache = function(e, t) { -var n = e + "/" + (t || ""); -return XRegExp.cache[n] || (XRegExp.cache[n] = XRegExp(e, t)); -}, XRegExp.copyAsGlobal = function(t) { -return e(t, "g"); -}, XRegExp.escape = function(e) { -return e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); -}, XRegExp.execAt = function(t, n, r, i) { -n = e(n, "g" + (i && p ? "y" : "")), n.lastIndex = r = r || 0; -var s = n.exec(t); -return i ? s && s.index === r ? s : null : s; -}, XRegExp.freezeTokens = function() { -XRegExp.addToken = function() { -throw Error("can't run addToken after freezeTokens"); -}; -}, XRegExp.isRegExp = function(e) { -return Object.prototype.toString.call(e) === "[object RegExp]"; -}, XRegExp.iterate = function(t, n, r, i) { -var s = e(n, "g"), o = -1, u; -while (u = s.exec(t)) r.call(i, u, ++o, t, s), s.lastIndex === u.index && s.lastIndex++; -n.global && (n.lastIndex = 0); -}, XRegExp.matchChain = function(t, n) { -return function r(t, i) { -var s = n[i].regex ? n[i] : { -regex: n[i] -}, o = e(s.regex, "g"), u = [], a; -for (a = 0; a < t.length; a++) XRegExp.iterate(t[a], o, function(e) { -u.push(s.backref ? e[s.backref] || "" : e[0]); -}); -return i === n.length - 1 || !u.length ? u : r(u, i + 1); -}([ t ], 0); -}, RegExp.prototype.apply = function(e, t) { -return this.exec(t[0]); -}, RegExp.prototype.call = function(e, t) { -return this.exec(t); -}, RegExp.prototype.exec = function(e) { -var n = f.exec.apply(this, arguments), i, s; -if (n) { -!l && n.length > 1 && r(n, "") > -1 && (s = RegExp(this.source, f.replace.call(t(this), "g", "")), f.replace.call(e.slice(n.index), s, function() { -for (var e = 1; e < arguments.length - 2; e++) arguments[e] === undefined && (n[e] = undefined); -})); -if (this._xregexp && this._xregexp.captureNames) for (var o = 1; o < n.length; o++) i = this._xregexp.captureNames[o - 1], i && (n[i] = n[o]); -!c && this.global && !n[0].length && this.lastIndex > n.index && this.lastIndex--; -} -return n; -}, c || (RegExp.prototype.test = function(e) { -var t = f.exec.call(this, e); -return t && this.global && !t[0].length && this.lastIndex > t.index && this.lastIndex--, !!t; -}), String.prototype.match = function(e) { -XRegExp.isRegExp(e) || (e = RegExp(e)); -if (e.global) { -var t = f.match.apply(this, arguments); -return e.lastIndex = 0, t; -} -return e.exec(this); -}, String.prototype.replace = function(e, t) { -var n = XRegExp.isRegExp(e), s, o, u; -return n && typeof t.valueOf() == "string" && t.indexOf("${") === -1 && h ? f.replace.apply(this, arguments) : (n ? e._xregexp && (s = e._xregexp.captureNames) : e += "", typeof t == "function" ? o = f.replace.call(this, e, function() { -if (s) { -arguments[0] = new String(arguments[0]); -for (var r = 0; r < s.length; r++) s[r] && (arguments[0][s[r]] = arguments[r + 1]); -} -return n && e.global && (e.lastIndex = arguments[arguments.length - 2] + arguments[0].length), t.apply(null, arguments); -}) : (u = this + "", o = f.replace.call(u, e, function() { -var e = arguments; -return f.replace.call(t, i, function(t, n, i) { -if (!n) { -var o = +i; -return o <= e.length - 3 ? e[o] : (o = s ? r(s, i) : -1, o > -1 ? e[o + 1] : t); -} -switch (n) { -case "$": -return "$"; -case "&": -return e[0]; -case "`": -return e[e.length - 1].slice(0, e[e.length - 2]); -case "'": -return e[e.length - 1].slice(e[e.length - 2] + e[0].length); -default: -var u = ""; -n = +n; -if (!n) return t; -while (n > e.length - 3) u = String.prototype.slice.call(n, -1) + u, n = Math.floor(n / 10); -return (n ? e[n] || "" : "$") + u; -} -}); -})), n && e.global && (e.lastIndex = 0), o); -}, String.prototype.split = function(e, t) { -if (!XRegExp.isRegExp(e)) return f.split.apply(this, arguments); -var n = this + "", r = [], i = 0, s, o; -if (t === undefined || +t < 0) t = Infinity; else { -t = Math.floor(+t); -if (!t) return []; -} -e = XRegExp.copyAsGlobal(e); -while (s = e.exec(n)) { -if (e.lastIndex > i) { -r.push(n.slice(i, s.index)), s.length > 1 && s.index < n.length && Array.prototype.push.apply(r, s.slice(1)), o = s[0].length, i = e.lastIndex; -if (r.length >= t) break; -} -e.lastIndex === s.index && e.lastIndex++; -} -return i === n.length ? (!f.test.call(e, "") || o) && r.push("") : r.push(n.slice(i)), r.length > t ? r.slice(0, t) : r; -}, XRegExp.addToken(/\(\?#[^)]*\)/, function(e) { -return f.test.call(o, e.input.slice(e.index + e[0].length)) ? "" : "(?:)"; -}), XRegExp.addToken(/\((?!\?)/, function() { -return this.captureNames.push(null), "("; -}), XRegExp.addToken(/\(\?<([$\w]+)>/, function(e) { -return this.captureNames.push(e[1]), this.hasNamedCapture = !0, "("; -}), XRegExp.addToken(/\\k<([\w$]+)>/, function(e) { -var t = r(this.captureNames, e[1]); -return t > -1 ? "\\" + (t + 1) + (isNaN(e.input.charAt(e.index + e[0].length)) ? "" : "(?:)") : e[0]; -}), XRegExp.addToken(/\[\^?]/, function(e) { -return e[0] === "[]" ? "\\b\\B" : "[\\s\\S]"; -}), XRegExp.addToken(/^\(\?([imsx]+)\)/, function(e) { -return this.setFlag(e[1]), ""; -}), XRegExp.addToken(/(?:\s+|#.*)+/, function(e) { -return f.test.call(o, e.input.slice(e.index + e[0].length)) ? "" : "(?:)"; -}, XRegExp.OUTSIDE_CLASS, function() { -return this.hasFlag("x"); -}), XRegExp.addToken(/\./, function() { -return "[\\s\\S]"; -}, XRegExp.OUTSIDE_CLASS, function() { -return this.hasFlag("s"); -}); -})(); - -var SyntaxHighlighter = function() { -function e(e) { -return e.split("\n"); -} -function t(e, t, n) { -n = Math.max(n || 0, 0); -for (var r = n; r < e.length; r++) if (e[r] == t) return r; -return -1; -} -function n(e, t) { -var n = {}, r; -for (r in e) n[r] = e[r]; -for (r in t) n[r] = t[r]; -return n; -} -function r(e) { -var t = { -"true": !0, -"false": !1 -}[e]; -return t == null ? e : t; -} -function i(t, n) { -var r = e(t); -for (var i = 0; i < r.length; i++) r[i] = n(r[i], i); -return r.join("\n"); -} -function s(e) { -return e.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, ""); -} -function o(e, t) { -return e == null || e.length == 0 || e == "\n" ? e : (e = e.replace(/' + e + "
    "; -})), e); -} -function u(e, t) { -var n = e.toString(); -while (n.length < t) n = "0" + n; -return n; -} -function a(e, t) { -var n = ""; -for (var r = 0; r < t; r++) n += " "; -return e.replace(/\t/g, n); -} -function f(t, n) { -function r(e, t, n) { -return e.substr(0, t) + u.substr(0, n) + e.substr(t + 1, e.length); -} -var s = e(t), o = " ", u = ""; -for (var a = 0; a < 50; a++) u += " "; -return t = i(t, function(e) { -if (e.indexOf(o) == -1) return e; -var t = 0; -while ((t = e.indexOf(o)) != -1) { -var i = n - t % n; -e = r(e, t, i); -} -return e; -}), t; -} -function l(e) { -var t = /|<br\s*\/?>/gi; -return e = e.replace(t, "\n"), m.config.stripBrs == 1 && (e = e.replace(t, "")), e; -} -function c(e) { -return e.replace(/^\s+|\s+$/g, ""); -} -function h(t) { -var n = e(l(t)), r = new Array, i = /^\s*/, s = 1e3; -for (var o = 0; o < n.length && s > 0; o++) { -var u = n[o]; -if (c(u).length == 0) continue; -var a = i.exec(u); -if (a == null) return t; -s = Math.min(a[0].length, s); -} -if (s > 0) for (var o = 0; o < n.length; o++) n[o] = n[o].substr(s); -return n.join("\n"); -} -function p(e, t) { -return e.index < t.index ? -1 : e.index > t.index ? 1 : e.length < t.length ? -1 : e.length > t.length ? 1 : 0; -} -function d(e, t) { -function n(e, t) { -return e[0]; -} -var r = 0, i = null, s = [], o = t.func ? t.func : n; -while ((i = t.regex.exec(e)) != null) { -var u = o(i, t); -typeof u == "string" && (u = [ new m.Match(u, i.index, t.css) ]), s = s.concat(u); -} -return s; -} -function v(e) { -var t = /(.*)((>|<).*)/; -return e.replace(m.regexLib.url, function(e) { -var n = "", r = null; -if (r = t.exec(e)) e = r[1], n = r[2]; -return '' + e + "" + n; -}); -} -var m = { -defaults: { -"class-name": "", -"first-line": 1, -"pad-line-numbers": !1, -highlight: null, -"smart-tabs": !0, -"tab-size": 4, -gutter: !0, -"auto-links": !0 -}, -config: { -space: " ", -stripBrs: !1, -strings: { -alert: "SyntaxHighlighter\n\n", -noBrush: "Can't find brush for: ", -brushNotHtmlScript: "Brush wasn't configured for html-script option: " -} -}, -brushes: {}, -regexLib: { -multiLineCComments: /\/\*[\s\S]*?\*\//gm, -singleLineCComments: /\/\/.*$/gm, -singleLinePerlComments: /#.*$/gm, -doubleQuotedString: /"([^\\"\n]|\\.)*"/g, -singleQuotedString: /'([^\\'\n]|\\.)*'/g, -multiLineDoubleQuotedString: new XRegExp('"([^\\\\"]|\\\\.)*"', "gs"), -multiLineSingleQuotedString: new XRegExp("'([^\\\\']|\\\\.)*'", "gs"), -xmlComments: /(<|<)!--[\s\S]*?--(>|>)/gm, -url: /\w+:\/\/[\w-.\/?%&=:@;]*/g, -phpScriptTags: { -left: /(<|<)\?=?/g, -right: /\?(>|>)/g -}, -aspScriptTags: { -left: /(<|<)%=?/g, -right: /%(>|>)/g -}, -scriptScriptTags: { -left: /(<|<)\s*script.*?(>|>)/gi, -right: /(<|<)\/\s*script\s*(>|>)/gi -} -} -}; -return m.Match = function(e, t, n) { -this.value = e, this.index = t, this.length = e.length, this.css = n, this.brushName = null; -}, m.Match.prototype.toString = function() { -return this.value; -}, m.Highlighter = function() {}, m.Highlighter.prototype = { -getParam: function(e, t) { -var n = this.params[e]; -return r(n == null ? t : n); -}, -create: function(e) { -return document.createElement(e); -}, -findMatches: function(e, t) { -var n = []; -if (e != null) for (var r = 0; r < e.length; r++) typeof e[r] == "object" && (n = n.concat(d(t, e[r]))); -return this.removeNestedMatches(n.sort(p)); -}, -removeNestedMatches: function(e) { -for (var t = 0; t < e.length; t++) { -if (e[t] === null) continue; -var n = e[t], r = n.index + n.length; -for (var i = t + 1; i < e.length && e[t] !== null; i++) { -var s = e[i]; -if (s === null) continue; -if (s.index > r) break; -s.index == n.index && s.length > n.length ? e[t] = null : s.index >= n.index && s.index < r && (e[i] = null); -} -} -return e; -}, -figureOutLineNumbers: function(e) { -var t = [], n = parseInt(this.getParam("first-line")); -return i(e, function(e, r) { -t.push(r + n); -}), t; -}, -isLineHighlighted: function(e) { -var n = this.getParam("highlight", []); -return typeof n != "object" && n.push == null && (n = [ n ]), t(n, e.toString()) != -1; -}, -getLineHtml: function(e, t, n) { -var r = [ "line", "number" + t, "index" + e, "alt" + (t % 2 == 0 ? 1 : 2).toString() ]; -return this.isLineHighlighted(t) && r.push("highlighted"), t == 0 && r.push("break"), '
    ' + n + "
    "; -}, -getLineNumbersHtml: function(t, n) { -var r = "", i = e(t).length, s = parseInt(this.getParam("first-line")), o = this.getParam("pad-line-numbers"); -o == 1 ? o = (s + i - 1).toString().length : isNaN(o) == 1 && (o = 0); -for (var a = 0; a < i; a++) { -var f = n ? n[a] : s + a, t = f == 0 ? m.config.space : u(f, o); -r += this.getLineHtml(a, f, t); -} -return r; -}, -getCodeLinesHtml: function(t, n) { -t = c(t); -var r = e(t), i = this.getParam("pad-line-numbers"), s = parseInt(this.getParam("first-line")), t = "", o = this.getParam("brush"); -for (var u = 0; u < r.length; u++) { -var a = r[u], f = /^( |\s)+/.exec(a), l = null, h = n ? n[u] : s + u; -f != null && (l = f[0].toString(), a = a.substr(l.length), l = l.replace(" ", m.config.space)), a = c(a), a.length == 0 && (a = m.config.space), t += this.getLineHtml(u, h, (l != null ? '' + l + "" : "") + a); -} -return t; -}, -getMatchesHtml: function(e, t) { -function n(e) { -var t = e ? e.brushName || s : s; -return t ? t + " " : ""; -} -var r = 0, i = "", s = this.getParam("brush", ""); -for (var u = 0; u < t.length; u++) { -var a = t[u], f; -if (a === null || a.length === 0) continue; -f = n(a), i += o(e.substr(r, a.index - r), f + "plain") + o(a.value, f + a.css), r = a.index + a.length + (a.offset || 0); -} -return i += o(e.substr(r), n() + "plain"), i; -}, -getHtml: function(e) { -var t = "", n = [ "syntaxhighlighter" ], r, i, o; -return className = "syntaxhighlighter", (gutter = this.getParam("gutter")) == 0 && n.push("nogutter"), n.push(this.getParam("class-name")), n.push(this.getParam("brush")), e = s(e).replace(/\r/g, " "), r = this.getParam("tab-size"), e = this.getParam("smart-tabs") == 1 ? f(e, r) : a(e, r), e = h(e), gutter && (o = this.figureOutLineNumbers(e)), i = this.findMatches(this.regexList, e), t = this.getMatchesHtml(e, i), t = this.getCodeLinesHtml(t, o), this.getParam("auto-links") && (t = v(t)), typeof navigator != "undefined" && navigator.userAgent && navigator.userAgent.match(/MSIE/) && n.push("ie"), t = '
    ' + '' + "" + "" + (gutter ? '" : "") + '" + "" + "" + "
    ' + this.getLineNumbersHtml(e) + "' + '
    ' + t + "
    " + "
    " + "
    ", t; -}, -init: function(e) { -this.params = n(m.defaults, e || {}); -}, -getKeywords: function(e) { -return e = e.replace(/^\s+|\s+$/g, "").replace(/\s+/g, "|"), "\\b(?:" + e + ")\\b"; -} -}, m; -}(); - -(function() { -function e() { -var e = "break case catch continue default delete do else false for function if in instanceof new null return super switch this throw true try typeof var while with", t = SyntaxHighlighter.regexLib; -this.regexList = [ { -regex: t.multiLineDoubleQuotedString, -css: "string" -}, { -regex: t.multiLineSingleQuotedString, -css: "string" -}, { -regex: t.singleLineCComments, -css: "comments" -}, { -regex: t.multiLineCComments, -css: "comments" -}, { -regex: /\s*#.*/gm, -css: "preprocessor" -}, { -regex: new RegExp(this.getKeywords(e), "gm"), -css: "keyword" -} ]; -} -e.prototype = new SyntaxHighlighter.Highlighter, e.aliases = [ "js", "jscript", "javascript" ], SyntaxHighlighter.brushes.JScript = e; -})(), function() { -var e = new SyntaxHighlighter.brushes.JScript; -e.init({}), syntaxHighlight = function(t) { -return e.getHtml(t); -}; -}(); - -// Presentor.js - -enyo.kind({ -name: "Presentor", -kind: null, -showInherited: !1, -showProtected: !1, -getByType: function(e, t) { -var n = []; -for (var r = 0, i; i = e[r]; r++) i.type == t && n.push(i); -return n; -}, -presentObject: function(e) { -switch (e.type) { -case "module": -return this.presentObjects(e.objects); -case "kind": -return this.presentKind(e); -case "function": -case "global": -return this.presentProperty(e); -} -}, -presentObjects: function(e) { -var t = this.groupFilter(e), n = "", r, i, s = !1, o = this.getByType(t, "kind"); -if (o.length) { -n += "

    Kinds

    "; -for (r = 0; i = o[r]; r++) n += "" + i.name + "
    ", n += this.presentComment(i.comment); -s = !0; -} -o = this.getByType(t, "function"); -if (o.length) { -n += "

    Functions

    "; -for (r = 0; i = o[r]; r++) i.group && (n += "<" + i.group + ">" + i.group + ""), n += ": function(" + i.value[0].arguments.join(", ") + ")
    ", n += this.presentComment(i.comment); -s = !0; -} -o = this.getByType(t, "global"); -if (o.length) { -n += "

    Variables

    "; -for (r = 0; i = o[r]; r++) n += this.presentComment(i.comment), i.group && (n += "<" + i.group + ">" + i.group + ""), n += " = ", n += this.presentExpression(i.value[0]), n += "
    "; -s = !0; -} -return s || (n += "

    This module has no public properties or functions to display.

    "), n; -}, -presentComment: function(e) { -return e ? "" + this.markupToHtml(e) + "" : ""; -}, -presentKind: function(e) { -return this.presentKindHeader(e) + this.presentKindSummary(e) + this.presentKindProperties(e); -}, -presentKindHeader: function(e) { -var t = ""; -return e.module && e.module.label && (t += "" + e.module.label + ""), t += "" + e.name + "", e.superkinds.length && (t += '
    ', t += e.name, enyo.forEach(e.superkinds, function(e) { -t += " :: " + e + ""; -}), t += "
    "), t; -}, -presentKindSummary: function(e) { -var t = ""; -return e.comment && (t += "

    Summary

    " + this.presentComment(e.comment)), t; -}, -presentKindProperties: function(e) { -return this.presentProperties(this.showInherited ? e.allProperties : e.properties, e); -}, -groupFilter: function(e) { -return enyo.filter(e, function(e) { -return e.name[0] !== "_" && (e.group == "public" || this.showProtected && e.group == "protected"); -}, this); -}, -presentProperties: function(e, t) { -var n = this.groupFilter(e), r = ""; -for (var i = 0, s; s = n[i]; i++) r += this.presentProperty(s, t); -return r; -}, -presentProperty: function(e, t) { -var n = "", r = e; -n += '', r.group && (n += "<" + r.group + ">" + r.group + ""); -var i = r.name.replace(".prototype", ""); -return r.object && t && t != r.object && (i = "" + r.object.name + "::" + i), n += ": ", r.value && r.value[0] && r.value[0].token == "function" ? n += "function(" + r.value[0].arguments.join(", ") + ")
    " : n += this.presentValue(r), n += this.presentComment(r.comment), n += "
    ", n; -}, -presentValue: function(e) { -var t, n = e.value; -return !n || !n[0] ? t = e.token : t = this.presentExpression(n[0]), t += "
    ", t; -}, -presentExpression: function(e) { -var t = e; -return t.comment ? this.presentComment(t.comment) : t.type == "block" ? "{

    " + this.presentBlock(t) + "
    }" : t.type == "array" ? "[
    " + this.presentArray(t) + "
    ]" : t.token; -}, -presentBlock: function(e) { -return this.presentProperties(e.properties); -}, -presentArray: function(e) { -var t = "", n = e.properties; -for (var r = 0, i; i = n[r]; r++) t += "" + r + ": " + this.presentExpression(i); -return t; -}, -presentColumns: function(e, t, n) { -var r = this.groupFilter(e), i = ""; -t && (i = t.name + "::"); -var s = n || 4, o = [], u = ""; -for (var a = 0, f = 0, l = 0; p = r[a]; a++) u += '' + p.name + "
    ", ++l == s && (o.push(u), u = "", l = 0); -return u && o.push(u), u = o.length ? "" + o.join("") + "" : "", u; -}, -markupToHtml: function(e) { -var t = Presentor.showdown.makeHtml(e || ""); -return t = t.replace(/
    ([\s\S]*?)<\/code><\/pre>/gm, function(e, t) {
    -return "
    " + syntaxHighlight(t) + "
    "; -}), t; -}, -inlineProperties: function(e, t) { -var n = [], r = function(e) { -e.parentHash = s.name; -}; -for (var i = 0, s; s = e[i]; i++) t[s.name] ? s.value && s.value[0] && s.value[0].properties && (enyo.forEach(s.value[0].properties, r), n = n.concat(s.value[0].properties)) : n.push(s); -return n; -}, -statics: { -showdown: new Showdown.converter -} -}); - -// PackagesEditor.js - -enyo.kind({ -name: "PackagesEditor", -kind: "Popup", -classes: "packages-editor", -events: { -onSave: "" -}, -components: [ { -kind: "Repeater", -onSetupItem: "setupItem", -components: [ { -components: [ { -name: "name", -kind: "Input" -}, { -name: "path", -kind: "Input" -}, { -kind: "Button", -content: "Delete", -ontap: "deletePkg" -} ] -} ] -}, { -kind: "Button", -content: "New...", -ontap: "newPkg" -}, { -tag: "hr" -}, { -kind: "Button", -content: "Cancel", -ontap: "hide" -}, { -kind: "Button", -content: "Save", -ontap: "save" -} ], -openWithPackages: function(e) { -this.show(), this.pkgs = e, this.load(); -}, -load: function() { -this.$.repeater.setCount(this.pkgs.length); -}, -setupItem: function(e, t) { -var n = this.pkgs[t.index]; -return t.item.$.name.setValue(n.name), t.item.$.path.setValue(n.path), !0; -}, -newPkg: function() { -this.pkgs.push({ -name: "", -path: "" -}), this.load(); -}, -deletePkg: function(e, t) { -this.pkgs.splice(t.index, 1), this.load(); -}, -save: function() { -var e = []; -for (var t = 0, n; n = this.$.repeater.getClientControls()[t]; t++) { -var r = n.$.name.getValue(), i = n.$.path.getValue(); -r && i && e.push({ -name: r, -path: i -}); -} -this.doSave({ -pkgs: e -}), this.hide(); -} -}); - -// PackageList.js - -enyo.kind({ -name: "PackageList", -components: [ { -kind: "Repeater", -components: [ { -components: [ { -kind: "Checkbox", -onchange: "cbChange" -} ] -} ] -}, { -name: "version", -style: "padding-top: 20px" -}, { -kind: "PackagesEditor", -modal: !0, -centered: !0, -floating: !0, -onSave: "savePackages" -} ], -published: { -version: "" -}, -events: { -onPackagesChange: "", -onLoaded: "" -}, -handlers: { -onSetupItem: "setupItem" -}, -create: function() { -this.inherited(arguments), this.versionChanged(); -}, -versionChanged: function() { -this.$.version.setContent("Content Version: " + this.version); -}, -fetchPackageData: function() { -(new enyo.Ajax({ -url: "assets/manifest.json" -})).response(this, function(e, t) { -this.setVersion(t.version), this.gotPackageData(t.packages); -}).go(); -}, -gotPackageData: function(e) { -this.pkgs = e, this.$.repeater.setCount(this.pkgs.length), this.doLoaded({ -packages: this.pkgs, -version: this.version -}); -}, -loadPackageData: function() { -this.pkgs ? this.gotPackageData(this.pkgs) : this.fetchPackageData(); -}, -savePackageData: function() {}, -setupItem: function(e, t) { -var n = this.pkgs[t.index], r = t.item.$.checkbox; -r.setContent(n.name), r.setChecked(!n.disabled); -}, -cbChange: function(e, t) { -var n = t.index, r = this.pkgs[n]; -r && (r.disabled = !e.getChecked(), this.savePackageData()), this.doPackagesChange({ -pkg: r -}); -} -}); - -// TabPanels.js - -enyo.kind({ -name: "TabPanels", -kind: "FittableRows", -components: [ { -name: "tabs", -kind: "Group", -defaultKind: "Button", -controlClasses: "tab" -}, { -name: "client", -style: "position: relative;", -fit: !0 -} ], -create: function() { -this.inherited(arguments), this.selectTab(0); -}, -addControl: function(e) { -e.isChrome || (e.addClass("enyo-fit"), e.showing = !1, this.$.tabs.createComponent({ -content: e.tabName || e.name, -ontap: "tabTap", -owner: this -})), this.inherited(arguments); -}, -selectTab: function(e) { -this.$.tabs.getControls()[e].setActive(!0); -for (var t = 0, n = this.getClientControls(), r; r = n[t]; t++) r.setShowing(t == e); -}, -tabTap: function(e) { -this.selectTab(e.indexInContainer()); -} -}); - -// SearchBar.js - -enyo.kind({ -name: "SearchBar", -events: { -onSearch: "" -}, -handlers: { -onkeyup: "search", -onchange: "search" -}, -components: [ { -xkind: "InputDecorator", -classes: "enyo-tool-decorator input-decorator", -style: "display: block;", -components: [ { -kind: "Input", -style: "width: 90%;" -}, { -kind: "Image", -src: "assets/search-input-search.png" -} ] -} ], -getValue: function() { -if (this.$.input.hasNode()) return this.$.input.node.value; -}, -search: function() { -this.doSearch({ -searchString: this.getValue() -}); -} -}); - -// App.js - -enyo.kind({ -name: "App", -fit: !0, -kind: "FittableColumns", -components: [ { -kind: "Analyzer", -onIndexReady: "indexReady" -}, { -name: "left", -kind: "TabPanels", -classes: "enyo-unselectable", -components: [ { -kind: "Scroller", -tabName: "Kinds", -components: [ { -name: "kinds", -allowHtml: !0 -} ] -}, { -kind: "Scroller", -tabName: "Modules", -components: [ { -name: "modules", -allowHtml: !0 -} ] -}, { -kind: "Scroller", -tabName: "Index", -components: [ { -kind: "SearchBar", -onSearch: "search" -}, { -name: "index", -allowHtml: !0 -} ] -}, { -name: "packages", -tabName: "Packages", -kind: "PackageList", -onPackagesChange: "loadPackages", -onLoaded: "packagesLoaded" -} ] -}, { -name: "doc", -kind: "FittableRows", -fit: !0, -components: [ { -name: "scope", -components: [ { -name: "inheritedCb", -kind: "Checkbox", -content: "show inherited", -onchange: "scopeChange" -}, { -name: "accessCb", -kind: "Checkbox", -content: "show protected", -style: "margin-left: 20px;", -onchange: "accessChange" -} ] -}, { -name: "header", -allowHtml: !0 -}, { -name: "tocFrame", -kind: "Scroller", -components: [ { -name: "toc", -allowHtml: !0 -} ] -}, { -name: "bodyFrame", -kind: "Scroller", -fit: !0, -classes: "enyo-selectable", -components: [ { -name: "indexBusy", -kind: "Image", -src: "assets/busy.gif", -style: "padding-left: 8px;", -showing: !1 -}, { -name: "body", -allowHtml: !0 -} ] -} ] -} ], -create: function() { -this.inherited(arguments), window.onhashchange = enyo.bind(this, "hashChange"), this.presentor = new Presentor, this.loadPackages(); -}, -loadPackages: function() { -this.index = this.$.analyzer.index = new Indexer, this.$.packages.loadPackageData(); -}, -packagesLoaded: function(e, t) { -document.title = "Enyo API Viewer (" + t.version + ")"; -var n = []; -return enyo.forEach(t.packages, function(e) { -e.disabled || n.push({ -path: e.path, -label: e.name -}); -}), this.walk(n), !0; -}, -walk: function(e) { -this.walking = !0, this.$.indexBusy.show(), this.$.analyzer.walk(e); -}, -indexReady: function() { -this.presentKinds(), this.presentModules(), this.presentIndex(), this.$.indexBusy.hide(), this.walking = !1, this.hashChange(); -}, -indexalize: function(e, t, n) { -var r = e ? enyo.filter(this.index.objects, e, this) : this.index.objects; -e(r[0]) && r.sort(this.moduleCompare), r = this.nameFilter(r); -var i = "", s; -for (var o = 0, u; u = r[o]; o++) { -var a = n(u).divider; -a && s != a && (s = a, i += "" + a + ""), i += enyo.macroize(t, n(u)); -} -return i; -}, -moduleCompare: function(e, t) { -var n, r; -try { -n = e.name.match("[^/]*.js$")[0], r = t.name.match("[^/]*.js$")[0]; -} catch (i) { -n = e.name, r = t.name; -} -return n.toUpperCase() < r.toUpperCase() ? -1 : n.toUpperCase() > r.toUpperCase() ? 1 : 0; -}, -nameFilter: function(e) { -return enyo.filter(e, function(e) { -return e.name && e.name[0] !== "_"; -}); -}, -presentFilteredIndex: function(e) { -var t = '{$object}{$topic}{$module}
    ', n = function(e) { -return { -link: e.topic || e.name, -topic: e.name.replace(".prototype", ""), -divider: e.name[0].toUpperCase(), -object: e.object && e.object.name ? e.object.name + "::" : "", -module: !e.object && e.module && e.module.name ? " [" + e.module.name.match("[^/]*.js$") + "]" : "" -}; -}; -this.$.index.setContent(this.indexalize(e, t, n)); -}, -presentIndex: function() { -var e = function(e) { -return e.name !== "published" && (e.group == "public" || e.group == "published"); -}; -this.presentFilteredIndex(e); -}, -presentModules: function() { -var e = function(e) { -return e.type == "module"; -}, t = '{$topic}
    ', n = function(e) { -return { -link: e.topic || e.name, -topic: e.name.match("[^/]*.js$"), -divider: e.name.match("[^/]*.js$")[0][0].toUpperCase() -}; -}; -this.$.modules.setContent(this.indexalize(e, t, n)); -}, -presentKinds: function() { -var e = function(e) { -return e.type == "kind" && e.group == "public"; -}, t = '{$topic}
    ', n = function(e) { -return { -link: e.topic || e.name, -topic: e.name, -divider: e.name.split(".")[0] -}; -}; -this.$.kinds.setContent(this.indexalize(e, t, n)); -}, -presentObject: function(e) { -if (!e || !e.type) return; -if (e.type === "kind") { -this.$.header.show(), this.presentKind(e); -return; -} -e.type === "module" ? (this.$.header.show(), this.$.header.setContent("" + e.name + "")) : (this.$.header.hide(), this.$.header.setContent("")), this.$.toc.setContent(""), this.$.doc.reflow(); -var t = ""; -e && (t = this.presentor.presentObject(e)), this.$.body.setContent(t); -}, -presentKind: function(e) { -this.$.header.setContent(this.presentor.presentKindHeader(e)); -var t = this.presentor.showInherited ? e.allProperties : e.properties; -t = this.presentor.inlineProperties(t, { -published: 1, -statics: 1, -events: 1 -}), t.sort(Indexer.nameCompare); -var n = this.presentor.presentColumns(t, e); -this.$.toc.setContent(n); -var r = this.presentor.presentKindSummary(e), i = this.presentor.presentKindProperties(e); -i && (r += "

    Properties

    " + i), this.$.body.setContent(r), this.$.doc.reflow(); -}, -presentModule: function(e) { -this.presentObject(e); -}, -moduleTap: function(e) { -this.presentModule(e.object); -}, -objectTap: function(e) { -this.presentObject(e.object); -}, -hashChange: function(e) { -this.selectTopic(this.getHashTopic()); -}, -getHashTopic: function() { -return window.location.hash.slice(1); -}, -selectTopic: function(e) { -this.topic = e; -var t = e.split("::"), n = t.shift(), r = t.shift(), i = this.index.findByName(n) || this.index.findByName("enyo." + n); -this.topicObject != i && (this.presentObject(i), this.topicObject = i, this.$.body.container.setScrollTop(0)); -if (r) { -var s = document.getElementsByName(r)[0]; -s && s.scrollIntoView(!0); -} -}, -scopeChange: function() { -this.presentor.showInherited = this.$.inheritedCb.getValue(), this.topicObject = null, this.selectTopic(this.topic); -}, -accessChange: function() { -this.presentor.showProtected = this.$.accessCb.getValue(), this.topicObject = null, this.selectTopic(this.topic); -}, -search: function(e, t) { -this.setSearchString(t.searchString.toLowerCase()); -}, -setSearchString: function(e) { -var t = function(t) { -return t.name !== "published" && (t.group == "public" || t.group == "published") && t.name.toLowerCase().indexOf(e) >= 0; -}; -this.presentFilteredIndex(t); -} -}); diff --git a/api/build/enyo.css b/api/build/enyo.css deleted file mode 100644 index 6d05291..0000000 --- a/api/build/enyo.css +++ /dev/null @@ -1,181 +0,0 @@ - -/* ../source/dom/dom.css */ - -/* things we always want */ -body { - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; -} - -/* allow hw-accelerated scrolling on platforms that support it */ -body.webkitOverflowScrolling { - -webkit-overflow-scrolling: touch; -} - -/* for apps */ -.enyo-document-fit { - margin: 0; - height: 100%; - /* note: giving html overflow: auto is odd and was only ever done to avoid duplication - however, android 4.04 sometimes does not hide nodes when their display is set to none - if document is overflow auto. - */ - position: relative; -} - -.enyo-body-fit { - margin: 0; - height: 100%; - /* helps prevent ios page scroll */ - overflow: auto; - position: relative; -} - -.enyo-no-touch-action { - -ms-touch-action: none; -} - -/* reset */ - -button { - font-size: inherit; - font-family: inherit; -} -button::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* user selection */ - -.enyo-unselectable { - cursor: default; - -ms-user-select: none; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; -} - -.enyo-unselectable::selection, .enyo-unselectable ::selection { - color: transparent; -} - -.enyo-selectable { - cursor: auto; - -ms-user-select: element; - -webkit-user-select: text; - -moz-user-select: text; - user-select: text; -} - -.enyo-selectable::selection, .enyo-selectable ::selection { - background: #3297FD; - color: #FFF; -} - -/* layout */ - -body .enyo-fit { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.enyo-clip { - overflow: hidden; -} - -.enyo-border-box { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* compositing */ - -.enyo-composite { - -webkit-transform: translateZ(0); - -moz-transform: translateZ(0); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - transform: translateZ(0); -} - - -/* ../source/touch/Thumb.css */ - -.enyo-thumb { - position: absolute; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; - background: #333; - border: 1px solid #666; - opacity: 0.75; - z-index: 1; -} - -.enyo-vthumb { - top: 0; - right: 2px; - width: 4px; -} - -.enyo-hthumb { - left: 0; - bottom: 2px; - height: 4px; -} - - -/* ../source/touch/Scroller.css */ - -.enyo-scroller { - position: relative; -} - -.enyo-fit.enyo-scroller { - position: absolute; -} - -.enyo-touch-scroller { - overflow: hidden; -} - -.enyo-touch-strategy-container { - overflow: hidden; -} - -.enyo-scrollee-fit { - height: 100%; -} - -/* ../source/ui/ui.css */ - -.enyo-inline, .enyo-tool-decorator { - display: inline-block; -} - -.enyo-children-inline > *, .enyo-tool-decorator > * { - display: inline-block; -} - -.enyo-children-middle > *, .enyo-tool-decorator > * { - vertical-align: middle; -} - -.enyo-positioned { - position: relative; -} - -.enyo-fill { - position: relative; - width: 100%; - height: 100%; -} - -.enyo-popup { - position: absolute; - z-index: 10; -} diff --git a/api/build/enyo.js b/api/build/enyo.js deleted file mode 100644 index e565f50..0000000 --- a/api/build/enyo.js +++ /dev/null @@ -1,4283 +0,0 @@ - -// enyo.js - -(function() { -var e = "enyo.js"; -enyo = window.enyo || {}, enyo.locateScript = function(e) { -var t = document.getElementsByTagName("script"); -for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { -i = r.getAttribute("src") || ""; -if (i.slice(-s) == e) return r.located = !0, { -path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), -node: r -}; -} -}, enyo.args = enyo.args || {}; -var t = enyo.locateScript(e); -if (t) { -enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); -for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; -} -})(); - -// ../../loader.js - -(function() { -enyo = window.enyo || {}, enyo.pathResolverFactory = function() { -this.paths = {}; -}, enyo.pathResolverFactory.prototype = { -addPath: function(e, t) { -return this.paths[e] = t; -}, -addPaths: function(e) { -if (e) for (var t in e) this.addPath(t, e[t]); -}, -includeTrailingSlash: function(e) { -return e && e.slice(-1) !== "/" ? e + "/" : e; -}, -rewritePattern: /\$([^\/\\]*)(\/)?/g, -rewrite: function(e) { -var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { -return t = !0, n(r[i]) || ""; -}, s = e; -do t = !1, s = s.replace(this.rewritePattern, i); while (t); -return s; -} -}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { -this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; -}, enyo.loaderFactory.prototype = { -verbose: !1, -loadScript: function(e) { -this.machine.script(e); -}, -loadSheet: function(e) { -this.machine.sheet(e); -}, -loadPackage: function(e) { -this.machine.script(e); -}, -report: function() {}, -load: function() { -this.more({ -index: 0, -depends: arguments || [] -}); -}, -more: function(e) { -if (e && this.continueBlock(e)) return; -var t = this.stack.pop(); -t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); -}, -finish: function() { -this.packageFolder = "", this.verbose && console.log("-------------- fini"); -for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); -}, -continueBlock: function(e) { -while (e.index < e.depends.length) { -var t = e.depends[e.index++]; -if (t) if (typeof t == "string") { -if (this.require(t, e)) return !0; -} else this.pathResolver.addPaths(t); -} -}, -require: function(e, t) { -var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); -n = r + n; -if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { -if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; -this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); -} -}, -getPathPrefix: function(e) { -var t = e.slice(0, 1); -return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; -}, -requireStylesheet: function(e) { -this.sheets.push(e), this.loadSheet(e); -}, -requireScript: function(e, t) { -this.modules.push({ -packageName: this.packageName, -rawPath: e, -path: t -}), this.loadScript(t); -}, -decodePackagePath: function(e) { -var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; -if (s.length) { -var a = s.pop() || s.pop() || ""; -a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; -for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { -s.splice(o, 1); -break; -} -n = s.join("/"); -for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { -s = s.slice(o + 1); -break; -} -for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); -t = s.join("-"); -} -return { -alias: t, -target: n, -folder: r, -manifest: i -}; -}, -aliasPackage: function(e) { -var t = this.decodePackagePath(e); -this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ -name: t.alias, -folder: t.folder -})), this.packageFolder = t.folder; -}, -requirePackage: function(e, t) { -t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); -} -}; -})(); - -// boot.js - -enyo.execUnsafeLocalFunction = function(e) { -typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); -}, enyo.machine = { -sheet: function(e) { -var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; -r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); -var i; -enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { -document.write(''); -}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { -less.refresh(!0); -})); -}, -script: function(e, t, n) { -if (!enyo.runtimeLoading) document.write(' - - - - - - diff --git a/assets/Diary.png b/assets/Diary.png deleted file mode 100644 index ae0450d94d017a53e5e603ec8d97dfc1312ee974..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7666 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 diff --git a/assets/check.png b/assets/check.png deleted file mode 100644 index f0f1bfecf26d4470b0f3f40fc7db17330e8d8748..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13502 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 z 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 Z0%!8y9*oUfC7+B17ACgF)e!gS{{fhy`m_K5 diff --git a/assets/month.png b/assets/month.png deleted file mode 100644 index 1fd74b23bbecfd96982af5629ee09c3829a37b4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26463 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

    U>J|3KdE|4E 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 c=NIH;H(z*VHaFBNk^w($b$zumRjW7u1t * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - /* float when not stretched */ - float: left; - clear: both; -} - -/* non-floating when stretched */ -.enyo-fittable-rows-layout.enyo-stretch > * { - float: none; - clear: none; -} - -/* setting to enforce margin collapsing */ -/* NOTE: rows cannot have margin left/right */ -.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { - float: left; - clear: both; - width: 100%; - /* note: harsh resets */ - margin-left: 0 !important; - margin-right: 0 !important; -} - -.enyo-fittable-columns-layout { - position: relative; - text-align: left; - white-space: nowrap; -} - -.enyo-fittable-columns-layout.enyo-center { - text-align: center; -} - -.enyo-fittable-columns-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - vertical-align: top; - display: inline-block; - white-space: normal; -} - -.enyo-fittable-columns-layout.enyo-tool-decorator > * { - vertical-align: middle; -} - -/* repair clobbered white-space setting for pre, code */ -.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { - white-space: pre; -} - -.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { - white-space: nowrap; -} - -/* NOTE: columns cannot have margin top/bottom */ -.enyo-fittable-columns-layout.enyo-stretch > * { - height: 100%; - /* note: harsh resets */ - margin-top: 0 !important; - margin-bottom: 0 !important; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/List.css */ - -.enyo-list { - position: relative; -} - -.enyo-list-port { - overflow: hidden; - position: relative; - height: 1000000px; -} - -.enyo-list-page, .enyo-list-holdingarea { - position: absolute; - left: 0; - right: 0; -} - -.enyo-list-holdingarea { - top: -10000px; -} - -.enyo-pinned-list-placeholder { - border: 1px solid red; - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-pinned-list-placeholder button { - width: 100px; height: 100%; - position: absolute; - top: 0; right: 0; -} - -.enyo-list-reorder-container { - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-animatedTopAndLeft { - -webkit-transition: top 0.1s linear, left 0.1s linear; - -moz-transition: top 0.1s linear, left 0.1s linear; - -o-transition: top 0.1s linear, left 0.1s linear; - transition: top 0.1s linear, left 0.1s linear; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/PulldownList.css */ - -.enyo-list-pulldown { - position: absolute; - bottom: 100%; - left: 0; - right: 0; -} - -.enyo-puller { - position: relative; - height: 50px; - font-size: 22px; - color: #444; - padding: 20px 0 0px 34px; -} - -.enyo-puller-text { - position: absolute; - left: 80px; - top: 22px; -} - -.enyo-puller-arrow { - position: relative; - background: #444; - width: 7px; - height: 28px; - transition: transform 0.3s; - -webkit-transition: -webkit-transform 0.3s; - -moz-transition: -moz-transform 0.3s; - -o-transition: -o-transform 0.3s; - -ms-transition: -ms-transform 0.3s; -} - -.enyo-puller-arrow:after { - content: " "; - height: 0; - width: 0; - position: absolute; - border: 10px solid transparent; - border-bottom-color: #444; - bottom: 100%; - left: 50%; - margin-left: -10px; -} - -.enyo-puller-arrow-up { - transform: rotate(0deg); - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -ms-transform: rotate(0deg); -} - -.enyo-puller-arrow-down { - transform: rotate(180deg); - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -o-transform: rotate(180deg); - -ms-transform: rotate(180deg); -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/arrangers/Arranger.css */ - -.enyo-arranger { - position: relative; - overflow: hidden; -} - -.enyo-arranger.enyo-fit { - position: absolute; -} - -.enyo-arranger > * { - position: absolute; - left: 0; - top: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.enyo-arranger-fit > * { - /* override any width/height set on panels */ - width: 100% !important; - height: 100% !important; - min-width: 0 !important; - min-height: 0 !important; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/Panels.css */ - -.enyo-panels { -} - -.enyo-panels-fit-narrow { -} - -@media all and (max-width: 800px) { - .enyo-panels-fit-narrow > * { - min-width: 100%; - max-width: 100%; - } -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/tree/source/Node.css */ - -.enyo-node { - cursor: default; - padding: 4px; -} - -.enyo-node img { - vertical-align: middle; - padding-right: 6px; -} - -.enyo-node-box { - overflow: hidden; -} - -.enyo-node-client { - position: relative; -} - -.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { - -ms-transition-property: height, top; - -ms-transition-duration: 0.2s, 0.2s; - -moz-transition-property: height, top; - -moz-transition-duration: 0.2s, 0.2s; - -o-transition-property: height, top; - -o-transition-duration: 0.2s, 0.2s; - -webkit-transition-property: height, top; - -webkit-transition-duration: 0.2s, 0.2s; - transition-property: height, top; - transition-duration: 0.2s, 0.2s; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/imageview/source/ImageViewPin.css */ - - -.pinDebug { - background:yellow; - border:1px solid yellow; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/css/onyx.less */ - -/* Onyx default parameters defined here */ -/* Fonts */ -/* ---------------------------------------*/ -/* Text Colors */ -/* ---------------------------------------*/ -/* Background Colors */ -/* ---------------------------------------*/ -/* Border Radius */ -/* ---------------------------------------*/ -/* Padding */ -/* ---------------------------------------*/ -/* Icon Sizes */ -/* ---------------------------------------*/ -/* Disabled Opacity */ -/* ---------------------------------------*/ -/* Gradient Overlays */ -/* ---------------------------------------*/ -/* Images */ -/* ---------------------------------------*/ -/* Onyx rules defined here */ -/* onyx-classes.less - combined CSS (less) files for all released Onyx controls - into single onyx.less file to avoid IE bug that allows - a maximum of 31 style sheets to be loaded before silently failing */ -.onyx { - color: #333333; - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; - font-size: 20px; - cursor: default; - background-color: #eaeaea; - /* remove automatic tap highlight color */ - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -/* prevent IE from inheriting line-height for these elements */ -.onyx button, -.onyx label, -.onyx input { - line-height: normal; -} -.onyx-selected { - background-color: #c4e3fe; -} -/* LESS pre-calculations */ -/* Individual Widget CSS */ -/* Icon.css */ -.onyx-icon, -.onyx-icon-toggle { - width: 32px; - height: 32px; - background-repeat: no-repeat; - display: inline-block; - vertical-align: middle; -} -.onyx-icon.onyx-icon-button.active, -.onyx-icon.onyx-icon-button.pressed, -.onyx-icon.onyx-icon-button:active:hover, -.onyx-icon-toggle.active { - background-position: 0 -32px; -} -.onyx-icon.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-icon.disabled:active:hover { - background-position: 0 0px; -} -/* Button.css */ -.onyx-button { - outline: 0; - color: #292929; - font-size: 16px; - text-align: center; - white-space: nowrap; - margin: 0; - padding: 6px 18px; - overflow: hidden; - border-radius: 3px; - /* for IE8 */ - - border: 1px solid #707070; - border: 1px solid rgba(15, 15, 15, 0.2); - /* - The border and the gradient interact in a strange way that - causes the bottom-border (top if the gradient is aligned top) - to be lighter than other borders. - We can fix it by using the darker bottom border below, but - then there are a few rogue pixels that end up very dark. - */ - - /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ - - box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); - background: #e1e1e1 url(../lib/onyx/images/gradient.png) repeat-x bottom; - background-size: contain; - /**/ - - text-overflow: ellipsis; - /* the following cause arcane problems on IE */ - - /* - min-width: 14px; - min-height: 20px; - */ - -} -/* - IE8 can't handle these selectors in tandem: - .onyx-button.active, .onyx-button:active:not([disabled]) { - - the effect is as if .onyx-button.active doesn't exist -*/ -.onyx-button.active, -.onyx-button.pressed { - background-image: url(../lib/onyx/images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button:active:hover:not([disabled]) { - background-image: url(../lib/onyx/images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button[disabled] { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-button > img { - padding: 0px 3px; -} -/* Remove the focused inner-border style in Firefox (Windows) */ -.onyx-button::-moz-focus-inner { - border: 0; -} -/* Checkbox.css */ -.onyx-checkbox { - cursor: pointer; - height: 32px; - width: 32px; - background: url(../lib/onyx/images/checkbox.png) no-repeat; - /* reset for ? */ - - margin: 0px; - /* these entries cause toggle-button and checkbox to line up properly*/ - - display: inline-block; - vertical-align: middle; -} -.onyx-checkbox[checked] { - background-position: 0px -32px; -} -.onyx-checkbox[disabled] { - opacity: 0.4; -} -/* Grabber.css */ -.onyx-grabber { - background: url(../lib/onyx/images/grabbutton.png) no-repeat center; - width: 23px; - height: 27px; -} -/* Popup.css */ -.onyx-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; -} -.onyx-popup-decorator { - position: relative; -} -/* Groupbox.css */ -.onyx-groupbox > * { - display: block; - /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ - - border-color: #aaaaaa; - border-style: solid; - border-width: 0 1px 1px 1px; - /*padding: 10px;*/ - - /* reset styles that make 'item' look bad if they happen to be there */ - - border-radius: 0; - margin: 0; - font-size: 16px; -} -.onyx-groupbox > *:first-child { - border-top-color: #aaaaaa; - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > *:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > *:first-child:last-child { - border-radius: 4px; -} -.onyx-groupbox-header { - padding: 2px 10px; - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; - /**/ - - background-color: #4c4c4c; - border: none; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 10px; -} -.onyx-groupbox .onyx-input-decorator { - display: block; -} -.onyx-groupbox > .onyx-input-decorator { - border-color: #aaaaaa; - border-width: 0 1px 1px 1px; - border-radius: 0; -} -.onyx-groupbox > .onyx-input-decorator:first-child { - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > .onyx-input-decorator:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > .onyx-input-decorator:first-child:last-child { - border-radius: 4px; -} -/* Input.css */ -.onyx-input-decorator { - padding: 6px 8px 10px 8px; - border-radius: 3px; - border: 1px solid; - border-color: rgba(0, 0, 0, 0.1); - margin: 0; -} -.onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - border-color: rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-input-decorator.onyx-disabled { - /* FIXME: needed to color a disabled input placeholder. */ - - /*-webkit-text-fill-color: #888;*/ - - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-input-decorator > input { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > input { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > input { - cursor: default; -} -/* Menu.css */ -.onyx-menu, -.onyx.onyx-menu { - min-width: 160px; - top: 100%; - left: 0; - margin-top: 2px; - padding: 3px 0; - border-radius: 3px; -} -.onyx-menu.onyx-menu-up { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 2px; -} -.onyx-toolbar .onyx-menu { - margin-top: 11px; - border-radius: 0 0 3px 3px; -} -.onyx-toolbar .onyx-menu.onyx-menu-up { - margin-top: 0; - margin-bottom: 10px; - border-radius: 3px 3px 0 0; -} -.onyx-menu-item { - display: block; - padding: 10px; -} -.onyx-menu-item:hover { - background: #284152; -} -.onyx-menu-divider, -.onyx-menu-divider:hover { - margin: 6px 0; - padding: 0; - border-bottom: 1px solid #aaa; -} -.onyx-menu-label { - cursor: default; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-menu-label:hover { - background: none; -} -/* customize a toolbar to support menus */ -.onyx-menu-toolbar, -.onyx-toolbar.onyx-menu-toolbar { - position: relative; - z-index: 10; - overflow: visible; -} -/* Picker.css */ -.onyx-picker-decorator .onyx-button { - padding: 10px 18px; -} -.onyx-picker { - top: 0; - margin-top: -3px; - min-width: 0; - width: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; - color: black; - background: #e1e1e1; -} -.onyx-picker.onyx-menu-up { - top: auto; - bottom: 0; - margin-top: 3px; - margin-bottom: -3px; -} -.onyx-picker .onyx-menu-item { - text-align: center; -} -.onyx-picker .onyx-menu-item:hover { - background-color: transparent; -} -.onyx-picker .onyx-menu-item.selected, -.onyx-picker .onyx-menu-item.active, -.onyx-picker .onyx-menu-item:active:hover { - border-top: 1px solid rgba(0, 0, 0, 0.1); - background-color: #cde7fe; - box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); -} -.onyx-picker .onyx-menu-item { - border-top: 1px solid rgba(255, 255, 255, 0.5); - border-bottom: 1px solid rgba(0, 0, 0, 0.2); -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, -.onyx-flyweight-picker :first-child > .onyx-menu-item { - border-top: none; -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, -.onyx-flyweight-picker :last-child > .onyx-menu-item { - border-bottom: none; -} -/* TextArea.css */ -.onyx-input-decorator > textarea { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* Remove scrollbars and resize handle */ - - resize: none; - overflow: auto; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > textarea { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > textarea { - cursor: default; -} -.onyx-textarea { - /* need >=50px for scrollbar to be usable on mac */ - - min-height: 50px; -} -/* RichText.css */ -.onyx-input-decorator > .onyx-richtext { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - min-height: 20px; - min-width: 100px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > .onyx-richtext { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > .onyx-richtext { - cursor: default; -} -/* RadioButton.css */ -.onyx-radiobutton { - padding: 8px 12px; - margin: 0; - outline: 0; - font-size: 16px; - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); - text-align: center; - /**/ - - background: #e7e7e7 url(../lib/onyx/images/gradient.png) repeat-x bottom; - /* IE8 */ - - border: 1px solid #333333; - border: 1px solid rgba(15, 15, 15, 0.2); - /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ - - border-right-color: rgba(0, 0, 0, 0); - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); -} -.onyx-radiobutton:first-child { - border-radius: 3px 0 0 3px; -} -.onyx-radiobutton:last-child { - border-radius: 0px 3px 3px 0px; - /* IE8 */ - - border-right: 1px solid #333333; - border-right: 1px solid rgba(15, 15, 15, 0.2); -} -.onyx-radiobutton.active { - color: #ffffff; - background: #0091f2 url(../lib/onyx/images/gradient-invert.png) repeat-x top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); -} -/* Scrim.css */ -.onyx-scrim { - z-index: 1; - /* - note: by using pointer-events we allow tapping on scrim - while it is fading out; however, this requires any showing classes - to set pointer events to auto or scrim will not function as expected. - */ - - pointer-events: none; -} -.onyx-scrim.onyx-scrim-translucent { - pointer-events: auto; - background-color: #000000; - opacity: 0.65; - filter: alpha(opacity=65); -} -.onyx-scrim.onyx-scrim-transparent { - pointer-events: auto; - background: transparent; -} -/* TabButton.css */ -.onyx-radiobutton.onyx-tabbutton { - padding: 8px 34px; - font-size: 20px; - border-radius: 0px; -} -/* ToggleButton.css */ -.onyx-toggle-button { - display: inline-block; - height: 32px; - line-height: 32px; - min-width: 64px; - vertical-align: middle; - text-align: center; - /* */ - - border-radius: 3px; - box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); - background: #8bba3d url(../lib/onyx/images/gradient-invert.png) repeat-x bottom; - background-size: auto 100%; - /* label */ - - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; -} -.onyx-toggle-button.off { - background-color: #b1b1b1 !important; -} -.onyx-toggle-button-knob { - display: inline-block; - width: 30px; - height: 30px; - margin: 1px; - border-radius: 3px; - background: #f6f6f6 url(../lib/onyx/images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-toggle-button .onyx-toggle-button-knob { - box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: right; -} -.onyx-toggle-button.off .onyx-toggle-button-knob { - box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: left; -} -.onyx-toggle-button.disabled, -.onyx-icon-button.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-toggle-content { - min-width: 32px; - padding: 0 6px; -} -.onyx-toggle-content.empty { - padding: 0; -} -.onyx-toggle-content.off { - float: right; -} -.onyx-toggle-content.on { - float: left; -} -/* Toolbar.css */ -.onyx-toolbar { - /* - line-height is unreliable for centering, instead - use vertical-align: middle to align - elements along a common centerline and use - padding to fill out the space. - */ - - padding: 9px 8px 10px 8px; - border: 1px solid #3A3A3A; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; - background-size: contain; - color: #ffffff; - /**/ - - white-space: nowrap; - overflow-y: visible; - font-size: 20px; -} -.onyx-toolbar-inline > *, -.enyo-fittable-columns-layout.onyx-toolbar-inline > * { - display: inline-block; - vertical-align: middle; - margin: 4px 6px 5px; - box-sizing: border-box; -} -.onyx-toolbar .onyx-icon-button { - margin: 3px 2px 1px; -} -.onyx-toolbar .onyx-button { - color: #f2f2f2; - background-color: #555656; - border-color: rgba(15, 15, 15, 0.5); - margin-top: 0; - margin-bottom: 0; - height: 36px; -} -.onyx-toolbar .onyx-input-decorator { - margin: 1px 3px; - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.1); - padding: 0px 6px 5px 6px; -} -.onyx-toolbar .onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-toolbar .onyx-input-decorator .onyx-input { - color: #e5e5e5; - font-size: 14px; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus { - color: #000000; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { - color: #dddddd; -} -/* Tooltip.css */ -.onyx-tooltip { - z-index: 20; - left: 0; - padding: 4px 6px; - margin-top: 4px; - margin-left: -6px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - color: #ffffff; - background: #216593 url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; - border-radius: 3px; - white-space: nowrap; -} -/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ -.onyx-tooltip.right-arrow { - left: 30px; -} -/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ -.onyx-tooltip::before { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - left: 16px; -} -.onyx-tooltip::after { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - margin-left: -12px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ -.onyx-tooltip.below { - top: 100%; -} -.onyx-tooltip.below.right-arrow::after { - border-bottom: 6px solid #1D587F; - top: -6px; -} -.onyx-tooltip.below.left-arrow::before { - border-bottom: 6px solid #1D587F; - top: -6px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ -.onyx-tooltip.above { - top: -100%; -} -.onyx-tooltip.above.right-arrow::after { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -.onyx-tooltip.above.left-arrow::before { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -/* ProgressBar.css */ -.onyx-progress-bar { - margin: 8px; - height: 8px; - border: 1px solid rgba(15, 15, 15, 0.2); - border-radius: 3px; - background: #b8b8b8 url(../lib/onyx/images/gradient-invert.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar { - height: 100%; - border-radius: 3px; - background: #58abef url(../lib/onyx/images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar.striped { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} -.onyx-progress-bar-bar.striped.animated { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -/* ProgressButton.css */ -.onyx-progress-button { - position: relative; - height: 36px; - line-height: 36px; - color: #f1f1f1; - font-size: 16px; - text-overflow: ellipsis; -} -.onyx-progress-button-bar { - height: 36px; -} -.onyx-progress-button-icon { - display: inline-block; - position: absolute; - top: 2px; - right: 0; -} -.onyx-progress-button-client { - display: inline-block; - position: absolute; - top: 0; - left: 0; - right: 36px; - margin-left: 8px; -} -.onyx-progress-button-client > * { - display: inline-block; -} -/* Slider.css */ -.onyx-slider { - position: relative; - margin: 8px 20px; -} -.onyx-slider-taparea { - position: absolute; - top: -11px; - height: 28px; - width: 100%; -} -.onyx-slider-knob { - position: relative; - height: 40px; - width: 40px; - background: url(../lib/onyx/images/slider-handle.png) left top no-repeat; - margin: -23px -20px; -} -.onyx-slider-knob.active, -.onyx-slider-knob.pressed, -.onyx-slider-knob:active:hover { - background-position: 0 -40px; -} -/* RangeSlider.css */ -.onyx-range-slider-knob { - top: -17px; -} -.onyx-range-slider-label { - position: relative; - top: -18px; - text-align: center; - white-space: nowrap; -} -/* Item.css */ -.onyx-item { - padding: 14px; -} -.onyx-highlight, -.onyx-highlight.onyx-swipeable-item-content { - background-color: #dedfdf; -} -.enyo-selected, -.enyo-selected.onyx-swipeable-item-content { - background-color: #c4e3fe; -} -.onyx-item.onyx-swipeable-item { - overflow: hidden; - padding: 0; -} -.onyx-swipeable-item-content { - background-color: #eaeaea; - box-sizing: border-box; - padding: 18px 6px; - min-height: 40px; -} -/* Spinner.css */ -.onyx-spinner { - width: 59px; - height: 58px; - display: inline-block; - background: url(../lib/onyx/images/spinner-dark.gif) no-repeat 0 0; -} -.onyx-spinner.onyx-light { - background: url(../lib/onyx/images/spinner-light.gif) no-repeat 0 0; -} -/* MoreToolbar.css */ -.onyx-more-toolbar { - overflow: visible; - position: relative; - z-index: 10; -} -.onyx-more-toolbar.active { - z-index: 11; -} -.onyx-more-menu { - left: auto; - right: 0px; - min-width: 0; -} -.onyx-more-toolbar .onyx-more-menu > * { - float: right; - clear: both; - margin: 5px; - margin-top: 5px; - margin-bottom: 5px; -} -.onyx-more-button { - background-image: url(../lib/onyx/images/more.png); - width: 32px; - height: 32px; -} -/* DatePicker.css */ -.onyx-datepicker-month { - min-width: 75px; -} -.onyx-datepicker-day { - min-width: 60px; -} -.onyx-datepicker-year { - min-width: 70px; -} -/* TimePicker.css */ -.onyx-timepicker-hour { - min-width: 60px; -} -.onyx-timepicker-minute { - min-width: 60px; -} -.onyx-timepicker-ampm { - min-width: 60px; -} -/* ButtonColors.css */ -.onyx-button.onyx-blue { - background-color: #35A8EE; - color: #F2F2F2; -} -.onyx-button.onyx-affirmative { - background-color: #91BA07; - color: #F2F2F2; -} -.onyx-button.onyx-negative { - background-color: #C51616; - color: #F2F2F2; -} -.onyx-button.onyx-dark { - background-color: #555656; - color: #F2F2F2; -} -.onyx-button.onyx-light { - background-color: #cacaca; - color: #2F2F2F; -} -/* ContextualPopup.css */ -.onyx-contextual-popup-title { - font-weight: bold; - padding: 24px 32px 0px; -} -.onyx-contextual-popup-scroller { - padding: 24px 32px; -} -.onyx-contextual-popup-action-buttons { - display: inline-block; - width: 100%; - text-align: center; -} -.onyx-contextual-popup-action-button { - margin-left: 5px; - margin-right: 5px; -} -.onyx-contextual-popup, -.onyx.onyx-contextual-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c; -} -/*setup the nub*/ -.onyx-contextual-popup::after { - content: ''; - position: absolute; - top: -10px; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; -} -/*for popups above activator*/ -.onyx-contextual-popup.vertical.above { - top: auto; - margin-top: -10px; - bottom: 100%; - margin-bottom: 10px; -} -/*for popups below activator*/ -.onyx-contextual-popup.vertical.below { - margin-top: 10px; -} -/*for popups on the left of the activator*/ -.onyx-contextual-popup.right.horizontal { - margin-left: -11px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.left.horizontal { - margin-left: 10px; -} -/*nub positioning*/ -/*horizontally centered nub*/ -.onyx-contextual-popup.vertical::after { - position: absolute; - left: 45%; - border-bottom: 10px solid #4c4c4c; - border-top: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -/*nub near horizontal left*/ -.onyx-contextual-popup.vertical.right::after { - left: 0%; - margin-left: 20px; -} -/*nub near horizontal right*/ -.onyx-contextual-popup.vertical.left::after { - left: 100%; - margin-left: -55px; -} -/*downward facing nub*/ -.onyx-contextual-popup.vertical.above::after { - top: 100%; - border-top: 10px solid #4c4c4c; - border-bottom: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right::after { - top: 0%; - margin-top: -10px; - border-bottom: 10px solid #4c4c4c; - border-left: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.left::after { - top: 0%; - margin-top: -10px; - border-right: 10px solid transparent; -} -/*nub positioning for left/right popups*/ -/*vertically centered nub for popups on left of activator*/ -.onyx-contextual-popup.right::after { - left: 100%; - top: 47%; - margin-right: 20px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on left of activator*/ -.onyx-contextual-popup.right.high::after { - top: 35px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on left of activator*/ -.onyx-contextual-popup.right.low::after { - top: 100%; - margin-top: -55px; - border-left: 10px solid #4C4C4C; -} -/*vertically centered nub for popups on right of activator*/ -.onyx-contextual-popup.left::after { - left: 0%; - margin-left: -20px; - top: 45%; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on right of activator*/ -.onyx-contextual-popup.left.high::after { - top: 35px; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on right of activator*/ -.onyx-contextual-popup.left.low::after { - top: 100%; - margin-top: -55px; - border-right: 10px solid #4C4C4C; -} -/*corners*/ -/*vertical top corners*/ -/*for popups on the left of the activator*/ -.onyx-contextual-popup.vertical.right.corner { - margin-left: 0px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.vertical.left.corner { - margin-left: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.vertical.below.right.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner::after { - top: 0%; - left: 100%; - margin-top: -10px; - margin-left: -19px; - border-right: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right.corner::after { - top: 0%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -/*vertical bottom corners*/ -.onyx-contextual-popup.left.above.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.right.above.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.vertical.left.above.corner::after { - top: 100%; - margin-left: -19px; - border-right: 10px solid #4C4C4C; - border-bottom: 10px solid transparent; - border-top: none; -} -.onyx-contextual-popup.vertical.right.above.corner::after { - top: 100%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-bottom: 10px solid transparent; - border-top: none; -} -/*horizontal bottom corners*/ -.onyx-contextual-popup.left.low.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.right.low.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.left.low.corner::after { - top: 100%; - left: 0%; - margin-top: -19px; - margin-left: -12px; - border-bottom: 10px solid #4c4c4c; - border-right: 10px solid #4c4c4c; -} -.onyx-contextual-popup.right.low.corner::after { - top: 100%; - left: 100%; - margin-top: -19px; - border-bottom: 10px solid#4c4c4c; - border-left: none; -} -/*horizontal top corners*/ -.onyx-contextual-popup.left.high.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.right.high.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.left.high.corner::after { - top: 0%; - left: 0%; - margin-top: -1px; - margin-left: -12px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -.onyx-contextual-popup.right.high.corner::after { - top: 0%; - left: 100%; - margin-top: -1px; - margin-left: -9px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -/* some default colors */ -.onyx-dark { - background-color: #555656; -} -.onyx-light { - background-color: #cacaca; -} -.onyx-green { - background-color: #91BA07; -} -.onyx-red { - background-color: #C51616; -} -.onyx-blue { - background-color: #35A8EE; -} - - -/* source/App.css */ - -/* - Put anything you reference with "url(../source)" in ../assets/ - This way, you can minify your application, and just remove the "source" folder for production -*/ -.nice-padding { - padding: 15px; -} diff --git a/build/app.js b/build/app.js deleted file mode 100644 index 7a17c89..0000000 --- a/build/app.js +++ /dev/null @@ -1,4447 +0,0 @@ - -// minifier: path aliases - -enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/source/"}); - -// FittableLayout.js - -enyo.kind({ -name: "enyo.FittableLayout", -kind: "Layout", -calcFitIndex: function() { -for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; -}, -getFitControl: function() { -var e = this.container.children, t = e[this.fitIndex]; -return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; -}, -getLastControl: function() { -var e = this.container.children, t = e.length - 1, n = e[t]; -while ((n = e[t]) && !n.showing) t--; -return n; -}, -_reflow: function(e, t, n, r) { -this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); -var i = this.getFitControl(); -if (!i) return; -var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); -f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); -var l = i.getBounds(); -o = l[n] - (a && a[n] || 0); -var c = this.getLastControl(); -if (c) { -var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; -if (c != i) { -var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; -u = v - d; -} else u = h; -} -var m = s - (o + u); -i.applyStyle(e, m + "px"); -}, -reflow: function() { -this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); -} -}), enyo.kind({ -name: "enyo.FittableColumnsLayout", -kind: "FittableLayout", -orient: "h", -layoutClass: "enyo-fittable-columns-layout" -}), enyo.kind({ -name: "enyo.FittableRowsLayout", -kind: "FittableLayout", -layoutClass: "enyo-fittable-rows-layout", -orient: "v" -}); - -// FittableRows.js - -enyo.kind({ -name: "enyo.FittableRows", -layoutKind: "FittableRowsLayout", -noStretch: !1 -}); - -// FittableColumns.js - -enyo.kind({ -name: "enyo.FittableColumns", -layoutKind: "FittableColumnsLayout", -noStretch: !1 -}); - -// FlyweightRepeater.js - -enyo.kind({ -name: "enyo.FlyweightRepeater", -published: { -count: 0, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -clientClasses: "", -clientStyle: "", -rowOffset: 0 -}, -events: { -onSetupItem: "", -onRenderRow: "" -}, -bottomUp: !1, -components: [ { -kind: "Selection", -onSelect: "selectDeselect", -onDeselect: "selectDeselect" -}, { -name: "client" -} ], -create: function() { -this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); -}, -noSelectChanged: function() { -this.noSelect && this.$.selection.clear(); -}, -multiSelectChanged: function() { -this.$.selection.setMulti(this.multiSelect); -}, -clientClassesChanged: function() { -this.$.client.setClasses(this.clientClasses); -}, -clientStyleChanged: function() { -this.$.client.setStyle(this.clientStyle); -}, -setupItem: function(e) { -this.doSetupItem({ -index: e, -selected: this.isSelected(e) -}); -}, -generateChildHtml: function() { -var e = ""; -this.index = null; -for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); -return e; -}, -previewDomEvent: function(e) { -var t = this.index = this.rowForEvent(e); -e.rowIndex = e.index = t, e.flyweight = this; -}, -decorateEvent: function(e, t, n) { -var r = t && t.index != null ? t.index : this.index; -t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); -}, -tap: function(e, t) { -if (this.noSelect || t.index === -1) return; -this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); -}, -selectDeselect: function(e, t) { -this.renderRow(t.key); -}, -getSelection: function() { -return this.$.selection; -}, -isSelected: function(e) { -return this.getSelection().isSelected(e); -}, -renderRow: function(e) { -if (e < this.rowOffset || e >= this.count + this.rowOffset) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ -rowIndex: e -})); -}, -fetchRowNode: function(e) { -if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); -}, -rowForEvent: function(e) { -if (!this.hasNode()) return -1; -var t = e.target; -while (t && t !== this.node) { -var n = t.getAttribute && t.getAttribute("data-enyo-index"); -if (n !== null) return Number(n); -t = t.parentNode; -} -return -1; -}, -prepareRow: function(e) { -if (e < 0 || e >= this.count) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -enyo.FlyweightRepeater.claimNode(this.$.client, t); -}, -lockRow: function() { -this.$.client.teardownChildren(); -}, -performOnRow: function(e, t, n) { -if (e < 0 || e >= this.count) return; -t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); -}, -statics: { -claimNode: function(e, t) { -var n; -t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); -for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); -} -} -}); - -// List.js - -enyo.kind({ -name: "enyo.List", -kind: "Scroller", -classes: "enyo-list", -published: { -count: 0, -rowsPerPage: 50, -bottomUp: !1, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -fixedHeight: !1, -reorderable: !1, -centerReorderContainer: !0, -reorderComponents: [], -pinnedReorderComponents: [], -swipeableComponents: [], -enableSwipe: !1, -persistSwipeableItem: !1 -}, -events: { -onSetupItem: "", -onSetupReorderComponents: "", -onSetupPinnedReorderComponents: "", -onReorder: "", -onSetupSwipeItem: "", -onSwipeDrag: "", -onSwipe: "", -onSwipeComplete: "" -}, -handlers: { -onAnimateFinish: "animateFinish", -onRenderRow: "rowRendered", -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onup: "up", -onholdpulse: "holdpulse" -}, -rowHeight: 0, -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0;" -} ] -} ], -reorderHoldTimeMS: 600, -draggingRowIndex: -1, -draggingRowNode: null, -placeholderRowIndex: -1, -dragToScrollThreshold: .1, -prevScrollTop: 0, -autoScrollTimeoutMS: 20, -autoScrollTimeout: null, -autoscrollPageY: 0, -pinnedReorderMode: !1, -initialPinPosition: -1, -itemMoved: !1, -currentPageNumber: -1, -completeReorderTimeout: null, -swipeIndex: null, -swipeDirection: null, -persistentItemVisible: !1, -persistentItemOrigin: null, -swipeComplete: !1, -completeSwipeTimeout: null, -completeSwipeDelayMS: 500, -normalSwipeSpeedMS: 200, -fastSwipeSpeedMS: 100, -percentageDraggedThreshold: .2, -importProps: function(e) { -e && e.reorderable && (this.touch = !0), this.inherited(arguments); -}, -create: function() { -this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); -}, -initComponents: function() { -this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); -}, -createReorderTools: function() { -this.createComponent({ -name: "reorderContainer", -classes: "enyo-list-reorder-container", -ondown: "sendToStrategy", -ondrag: "sendToStrategy", -ondragstart: "sendToStrategy", -ondragfinish: "sendToStrategy", -onflick: "sendToStrategy" -}); -}, -createStrategy: function() { -this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); -}, -createSwipeableComponents: function() { -for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { -owner: this.owner -}); -}, -rendered: function() { -this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); -}, -resizeHandler: function() { -this.inherited(arguments), this.refresh(); -}, -bottomUpChanged: function() { -this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); -}, -noSelectChanged: function() { -this.$.generator.setNoSelect(this.noSelect); -}, -multiSelectChanged: function() { -this.$.generator.setMultiSelect(this.multiSelect); -}, -toggleSelectedChanged: function() { -this.$.generator.setToggleSelected(this.toggleSelected); -}, -countChanged: function() { -this.hasNode() && this.updateMetrics(); -}, -sendToStrategy: function(e, t) { -this.$.strategy.dispatchEvent("on" + t.type, t, e); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -holdpulse: function(e, t) { -if (!this.getReorderable() || this.isReordering()) return; -if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; -}, -dragstart: function(e, t) { -if (this.isReordering()) return !0; -if (this.isSwipeable()) return this.swipeDragStart(e, t); -}, -drag: function(e, t) { -if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; -if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; -}, -dragfinish: function(e, t) { -this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); -}, -up: function(e, t) { -this.isReordering() && this.finishReordering(e, t); -}, -generatePage: function(e, t) { -this.page = e; -var n = this.rowsPerPage * this.page; -this.$.generator.setRowOffset(n); -var r = Math.min(this.count - n, this.rowsPerPage); -this.$.generator.setCount(r); -var i = this.$.generator.generateChildHtml(); -t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); -var s = t.getBounds().height; -!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); -if (!this.fixedHeight) { -var o = this.getPageHeight(e); -this.pageHeights[e] = s, this.portSize += s - o; -} -}, -pageForRow: function(e) { -return Math.floor(e / this.rowsPerPage); -}, -preserveDraggingRowNode: function(e) { -this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); -}, -update: function(e) { -var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; -this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); -}, -getPageRowHeights: function(e) { -var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); -for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { -height: s.height, -width: s.width -}); -return t; -}, -updateRowBounds: function(e) { -this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); -}, -updateRowBoundsAtIndex: function(e, t, n) { -var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); -t[e].height = i.height, t[e].width = i.width; -}, -updateForPosition: function(e) { -this.update(this.calcPos(e)); -}, -calcPos: function(e) { -return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; -}, -adjustBottomPage: function() { -var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; -this.positionPage(e.pageNo, e); -}, -adjustPortSize: function() { -this.scrollerHeight = this.getBounds().height; -var e = Math.max(this.scrollerHeight, this.portSize); -this.$.port.applyStyle("height", e + "px"); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e); -t.applyStyle(this.pageBound, n + "px"); -}, -pageToPosition: function(e) { -var t = 0, n = e; -while (n > 0) n--, t += this.getPageHeight(n); -return t; -}, -positionToPageInfo: function(e) { -var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; -while (n >= 0) t++, r = this.getPageHeight(t), n -= r; -return t = Math.max(t, 0), { -no: t, -height: r, -pos: n + r, -startRow: t * this.rowsPerPage, -endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) -}; -}, -isPageInRange: function(e) { -return e == Math.max(0, Math.min(this.pageCount - 1, e)); -}, -getPageHeight: function(e) { -var t = this.pageHeights[e]; -if (!t) { -var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); -t = this.defaultPageHeight * (r / this.rowsPerPage); -} -return Math.max(1, t); -}, -invalidatePages: function() { -this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); -}, -invalidateMetrics: function() { -this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); -}, -scroll: function(e, t) { -var n = this.inherited(arguments), r = this.getScrollTop(); -return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); -}, -setScrollTop: function(e) { -this.update(e), this.inherited(arguments), this.twiddle(); -}, -getScrollPosition: function() { -return this.calcPos(this.getScrollTop()); -}, -setScrollPosition: function(e) { -this.setScrollTop(this.calcPos(e)); -}, -scrollToBottom: function() { -this.update(this.getScrollBounds().maxTop), this.inherited(arguments); -}, -scrollToRow: function(e) { -var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); -this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); -if (t == this.p0 || t == this.p1) { -var i = this.$.generator.fetchRowNode(e); -if (i) { -var s = i.offsetTop; -this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); -var o = this.getScrollPosition() + s; -this.setScrollPosition(o); -} -} -}, -scrollToStart: function() { -this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); -}, -scrollToEnd: function() { -this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); -}, -refresh: function() { -this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); -}, -reset: function() { -this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); -}, -getSelection: function() { -return this.$.generator.getSelection(); -}, -select: function(e, t) { -return this.getSelection().select(e, t); -}, -deselect: function(e) { -return this.getSelection().deselect(e); -}, -isSelected: function(e) { -return this.$.generator.isSelected(e); -}, -renderRow: function(e) { -this.$.generator.renderRow(e); -}, -rowRendered: function(e, t) { -this.updateRowBounds(t.rowIndex); -}, -prepareRow: function(e) { -this.$.generator.prepareRow(e); -}, -lockRow: function() { -this.$.generator.lockRow(); -}, -performOnRow: function(e, t, n) { -this.$.generator.performOnRow(e, t, n); -}, -animateFinish: function(e) { -return this.twiddle(), !0; -}, -twiddle: function() { -var e = this.getStrategy(); -enyo.call(e, "twiddle"); -}, -pageForPageNumber: function(e, t) { -return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; -}, -shouldStartReordering: function(e, t) { -return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; -}, -startReordering: function(e) { -this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); -}, -buildReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -styleReorderContainer: function(e) { -this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); -}, -appendNodeToReorderContainer: function(e) { -this.$.reorderContainer.createComponent({ -allowHtml: !0, -content: e.innerHTML -}).render(); -}, -centerReorderContainerOnPointer: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; -this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); -}, -positionReorderContainer: function(e, t) { -this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); -}, -setPositionReorderContainerTimeout: function() { -this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { -this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); -}), 100); -}, -clearPositionReorderContainerTimeout: function() { -this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); -}, -shouldDoReorderDrag: function() { -return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; -}, -reorderDrag: function(e) { -this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); -}, -updatePlaceholderPosition: function(e) { -var t = this.getRowIndexFromCoordinate(e); -t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); -}, -positionReorderNode: function(e) { -var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; -r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); -}, -checkForAutoScroll: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; -this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); -}, -stopAutoScrolling: function() { -this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); -}, -startAutoScrolling: function() { -this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); -}, -autoScroll: function() { -this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ -ddx: 0, -ddy: 0 -}), this.updatePlaceholderPosition(this.autoscrollPageY); -}, -movePlaceholderToIndex: function(e) { -var t, n; -if (e < 0) return; -e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); -var r = this.pageForRow(e); -r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; -}, -finishReordering: function(e, t) { -if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; -return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; -}, -moveReorderedContainerToDroppedPosition: function() { -var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); -this.positionReorderContainer(n, t); -}, -completeFinishReordering: function(e) { -this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); -if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { -this.beginPinnedReorder(e); -return; -} -this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); -}, -beginPinnedReorder: function(e) { -this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { -index: this.draggingRowIndex -})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; -}, -emptyAndHideReorderContainer: function() { -this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); -}, -buildPinnedReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -reorderRows: function(e) { -this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); -}, -makeReorderEvent: function(e) { -return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; -}, -positionReorderedNode: function() { -if (!this.removedInitialPage) { -var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); -e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; -if (this.currentPageNumber != this.initialPageNumber) { -var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); -this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); -} -} -}, -updateListIndices: function() { -if (this.shouldDoRefresh()) { -this.refresh(), this.correctPageHeights(); -return; -} -var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; -if (n === 1) { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); -for (i = t - 1, s = t; i >= e; i--) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); -} -r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); -} else { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); -for (i = e + 1, s = e; i <= t; i++) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); -} -} -}, -shouldDoRefresh: function() { -return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; -}, -getNodeStyle: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) return; -var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); -return { -h: r.height, -w: r.width, -left: n.left, -top: n.top -}; -}, -getRelativeOffset: function(e, t) { -var n = { -top: 0, -left: 0 -}; -if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); -return n; -}, -replaceNodeWithPlaceholder: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) { -enyo.log("No node - " + e); -return; -} -this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); -var n = this.pageForPageNumber(this.currentPageNumber); -n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); -}, -createPlaceholderNode: function(e) { -var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); -return t.style.height = n.height + "px", t.style.width = n.width + "px", t; -}, -removePlaceholderNode: function() { -this.removeNode(this.placeholderNode), this.placeholderNode = null; -}, -removeDraggingRowNode: function() { -this.draggingRowNode = null; -var e = this.$.holdingarea.hasNode(); -e.innerHTML = ""; -}, -removeNode: function(e) { -if (!e || !e.parentNode) return; -e.parentNode.removeChild(e); -}, -updatePageHeight: function(e) { -if (e < 0) return; -var t = this.pageForPageNumber(e, !0); -if (t) { -var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); -this.pageHeights[e] = r, this.portSize += r - n; -} -}, -updatePagePositions: function(e) { -this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); -}, -correctPageHeights: function() { -this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); -}, -hideNode: function(e) { -return e.style.display = "none", e; -}, -showNode: function(e) { -return e.style.display = "block", e; -}, -dropPinnedRow: function(e) { -this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); -return; -}, -cancelPinnedMode: function(e) { -this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); -}, -getRowIndexFromCoordinate: function(e) { -var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; -if (t < 0) return -1; -var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; -if (!r) return this.count; -var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; -for (var u = n.startRow; u <= n.endRow; ++u) { -if (u === this.placeholderRowIndex) { -o += s; -if (o >= i) return -1; -} -if (u !== this.draggingRowIndex) { -o += r[u].height; -if (o >= i) return u; -} -} -return u; -}, -getIndexPosition: function(e) { -return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); -}, -setItemPosition: function(e, t) { -var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; -e.addStyles(i); -}, -setItemBounds: function(e, t) { -var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; -e.addStyles(r); -}, -reorderScroll: function(e, t) { -this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); -}, -hideReorderingRow: function() { -var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); -e && (this.hiddenNode = this.hideNode(e)); -}, -isReordering: function() { -return this.draggingRowIndex > -1; -}, -isSwiping: function() { -return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; -}, -swipeDragStart: function(e, t) { -return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); -}, -swipeDrag: function(e, t) { -return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; -}, -swipeDragFinish: function(e, t) { -if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { -if (!this.isSwiping()) return !1; -var n = this.calcPercentageDragged(this.draggedXDistance); -n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); -} -return this.preventDragPropagation; -}, -isSwipeable: function() { -return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; -}, -positionSwipeableContainer: function(e, t) { -var n = this.$.generator.fetchRowNode(e); -if (!n) return; -var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; -this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); -}, -calcNewDragPosition: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; -return s; -}, -dragSwipeableComponents: function(e) { -this.$.swipeableComponents.applyStyle("left", e + "px"); -}, -startSwipe: function(e) { -e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); -}, -dragPersistentItem: function(e) { -var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); -this.$.swipeableComponents.applyStyle("left", n + "px"); -}, -dragFinishPersistentItem: function(e) { -var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; -this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); -}, -setPersistentItemOrigin: function(e) { -this.persistentItemOrigin = e == 1 ? "left" : "right"; -}, -calcPercentageDragged: function(e) { -return Math.abs(e / this.$.swipeableComponents.getBounds().width); -}, -swipe: function(e) { -this.swipeComplete = !0, this.animateSwipe(0, e); -}, -backOutSwipe: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; -this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; -}, -bounceItem: function(e) { -var t = this.$.swipeableComponents.getBounds(); -t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); -}, -slideAwayItem: function() { -var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; -this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -clearSwipeables: function() { -this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -completeSwipe: function(e) { -this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ -index: this.swipeIndex, -xDirection: this.swipeDirection -})), this.swipeIndex = null, this.swipeDirection = null; -}, -animateSwipe: function(e, t) { -var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; -this.stopAnimateSwipe(); -var u = enyo.bind(this, function() { -var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); -i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { -this.completeSwipe(); -}), this.completeSwipeDelayMS)); -}); -this.job = enyo.requestAnimationFrame(u); -}, -stopAnimateSwipe: function() { -this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); -} -}); - -// PulldownList.js - -enyo.kind({ -name: "enyo.PulldownList", -kind: "List", -touch: !0, -pully: null, -pulldownTools: [ { -name: "pulldown", -classes: "enyo-list-pulldown", -components: [ { -name: "puller", -kind: "Puller" -} ] -} ], -events: { -onPullStart: "", -onPullCancel: "", -onPull: "", -onPullRelease: "", -onPullComplete: "" -}, -handlers: { -onScrollStart: "scrollStartHandler", -onScrollStop: "scrollStopHandler", -ondragfinish: "dragfinish" -}, -pullingMessage: "Pull down to refresh...", -pulledMessage: "Release to refresh...", -loadingMessage: "Loading...", -pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", -pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", -loadingIconClass: "", -create: function() { -var e = { -kind: "Puller", -showing: !1, -text: this.loadingMessage, -iconClass: this.loadingIconClass, -onCreate: "setPully" -}; -this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); -}, -initComponents: function() { -this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); -}, -resetStrategyKind: function() { -return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; -}, -setPully: function(e, t) { -this.pully = t.originator; -}, -scrollStartHandler: function() { -this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; -}, -scroll: function(e, t) { -var n = this.inherited(arguments); -this.completingPull && this.pully.setShowing(!1); -var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); -return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; -}, -scrollStopHandler: function() { -this.completingPull && (this.completingPull = !1, this.doPullComplete()); -}, -dragfinish: function() { -if (this.firedPull) { -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); -} -}, -completePull: function() { -this.completingPull = !0; -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(this.pullHeight), e.start(); -}, -pullStart: function() { -this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); -}, -pull: function() { -this.setPulled(), this.doPull(); -}, -pullCancel: function() { -this.setPulling(), this.doPullCancel(); -}, -pullRelease: function() { -this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); -}, -setPulling: function() { -this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); -}, -setPulled: function() { -this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); -} -}), enyo.kind({ -name: "enyo.Puller", -classes: "enyo-puller", -published: { -text: "", -iconClass: "" -}, -events: { -onCreate: "" -}, -components: [ { -name: "icon" -}, { -name: "text", -tag: "span", -classes: "enyo-puller-text" -} ], -create: function() { -this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); -}, -textChanged: function() { -this.$.text.setContent(this.text); -}, -iconClassChanged: function() { -this.$.icon.setClasses(this.iconClass); -} -}); - -// AroundList.js - -enyo.kind({ -name: "enyo.AroundList", -kind: "enyo.List", -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "aboveClient" -}, { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "belowClient" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0px;" -} ] -} ], -aboveComponents: null, -initComponents: function() { -this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { -owner: this.owner -}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { -owner: this.owner -}); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; -n += r, t.applyStyle(this.pageBound, n + "px"); -}, -scrollToContentStart: function() { -var e = this.bottomUp ? this.belowHeight : this.aboveHeight; -this.setScrollPosition(e); -} -}); - -// Slideable.js - -enyo.kind({ -name: "enyo.Slideable", -kind: "Control", -published: { -axis: "h", -value: 0, -unit: "px", -min: 0, -max: 0, -accelerated: "auto", -overMoving: !0, -draggable: !0 -}, -events: { -onAnimateFinish: "", -onChange: "" -}, -preventDragPropagation: !1, -tools: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorComplete" -} ], -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -kDragScalar: 1, -dragEventProp: "dx", -unitModifier: !1, -canTransform: !1, -create: function() { -this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); -}, -initComponents: function() { -this.createComponents(this.tools), this.inherited(arguments); -}, -rendered: function() { -this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); -}, -resizeHandler: function() { -this.inherited(arguments), this.updateDragScalar(); -}, -canModifyUnit: function() { -if (!this.canTransform) { -var e = this.getInitialStyleValue(this.hasNode(), this.boundary); -e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); -} -}, -getInitialStyleValue: function(e, t) { -var n = enyo.dom.getComputedStyle(e); -return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; -}, -updateBounds: function(e, t) { -var n = {}; -n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); -}, -updateDragScalar: function() { -if (this.unit == "%") { -var e = this.getBounds()[this.dimension]; -this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); -} -}, -transformChanged: function() { -this.canTransform = enyo.dom.canTransform(); -}, -acceleratedChanged: function() { -enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); -}, -axisChanged: function() { -var e = this.axis == "h"; -this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; -}, -setInlineStyles: function(e, t) { -var n = {}; -this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); -}, -valueChanged: function(e) { -var t = this.value; -this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); -}, -getAnimator: function() { -return this.$.animator; -}, -isAtMin: function() { -return this.value <= this.calcMin(); -}, -isAtMax: function() { -return this.value >= this.calcMax(); -}, -calcMin: function() { -return this.min; -}, -calcMax: function() { -return this.max; -}, -clampValue: function(e) { -var t = this.calcMin(), n = this.calcMax(); -return Math.max(t, Math.min(e, n)); -}, -dampValue: function(e) { -return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); -}, -dampBound: function(e, t, n) { -var r = e; -return r * n < t * n && (r = t + (r - t) / 4), r; -}, -percentToPixels: function(e, t) { -return Math.floor(t / 100 * e); -}, -pixelsToPercent: function(e) { -var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; -return e / t * 100; -}, -shouldDrag: function(e) { -return this.draggable && e[this.shouldDragProp]; -}, -isOob: function(e) { -return e > this.calcMax() || e < this.calcMin(); -}, -dragstart: function(e, t) { -if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; -}, -drag: function(e, t) { -if (this.dragging) { -t.preventDefault(); -var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; -return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; -} -}, -dragfinish: function(e, t) { -if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; -}, -completeDrag: function(e) { -this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); -}, -isAnimating: function() { -return this.$.animator.isAnimating(); -}, -play: function(e, t) { -this.$.animator.play({ -startValue: e, -endValue: t, -node: this.hasNode() -}); -}, -animateTo: function(e) { -this.play(this.value, e); -}, -animateToMin: function() { -this.animateTo(this.calcMin()); -}, -animateToMax: function() { -this.animateTo(this.calcMax()); -}, -animateToMinMax: function(e) { -e ? this.animateToMin() : this.animateToMax(); -}, -animatorStep: function(e) { -return this.setValue(e.value), !0; -}, -animatorComplete: function(e) { -return this.doAnimateFinish(e), !0; -}, -toggleMinMax: function() { -this.animateToMinMax(!this.isAtMin()); -} -}); - -// Arranger.js - -enyo.kind({ -name: "enyo.Arranger", -kind: "Layout", -layoutClass: "enyo-arranger", -accelerated: "auto", -dragProp: "ddx", -dragDirectionProp: "xDirection", -canDragProp: "horizontal", -incrementalPoints: !1, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n._arranger = null; -this.inherited(arguments); -}, -arrange: function(e, t) {}, -size: function() {}, -start: function() { -var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; -if (this.incrementalPoints) { -var r = Math.abs(t - e) - 2, i = e; -while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; -} -n.push(this.container.toIndex); -}, -finish: function() {}, -calcArrangementDifference: function(e, t, n, r) {}, -canDragEvent: function(e) { -return e[this.canDragProp]; -}, -calcDragDirection: function(e) { -return e[this.dragDirectionProp]; -}, -calcDrag: function(e) { -return e[this.dragProp]; -}, -drag: function(e, t, n, r, i) { -var s = this.measureArrangementDelta(-e, t, n, r, i); -return s; -}, -measureArrangementDelta: function(e, t, n, r, i) { -var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; -return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; -}, -_arrange: function(e) { -this.containerBounds || this.reflow(); -var t = this.getOrderedControls(e); -this.arrange(t, e); -}, -arrangeControl: function(e, t) { -e._arranger = enyo.mixin(e._arranger || {}, t); -}, -flow: function() { -this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { -enyo.dom.accelerate(n, this.accelerated); -if (enyo.platform.safari) { -var r = n.children; -for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); -} -} -}, -reflow: function() { -var e = this.container.hasNode(); -this.containerBounds = e ? { -width: e.clientWidth, -height: e.clientHeight -} : {}, this.size(); -}, -flowArrangement: function() { -var e = this.container.arrangement; -if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); -}, -flowControl: function(e, t) { -enyo.Arranger.positionControl(e, t); -var n = t.opacity; -n != null && enyo.Arranger.opacifyControl(e, n); -}, -getOrderedControls: function(e) { -var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; -for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); -return this.controlsIndex = t, i; -}, -statics: { -positionControl: function(e, t, n) { -var r = n || "px"; -if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { -var i = t.left, s = t.top; -i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { -translateX: i || null, -translateY: s || null -}); -} else e.setBounds(t, n); -}, -opacifyControl: function(e, t) { -var n = t; -n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); -} -} -}); - -// CardArranger.js - -enyo.kind({ -name: "enyo.CardArranger", -kind: "Arranger", -layoutClass: "enyo-arranger enyo-arranger-fit", -calcArrangementDifference: function(e, t, n, r) { -return this.containerBounds.width; -}, -arrange: function(e, t) { -for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { -opacity: s -}); -}, -start: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); -this.inherited(arguments); -} -}); - -// CardSlideInArranger.js - -enyo.kind({ -name: "enyo.CardSlideInArranger", -kind: "CardArranger", -start: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -var i = this.container.fromIndex; -t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -arrange: function(e, t) { -var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; -for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { -left: l -}); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null -}); -this.inherited(arguments); -} -}); - -// CarouselArranger.js - -enyo.kind({ -name: "enyo.CarouselArranger", -kind: "Arranger", -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; -n.height -= t.top + t.bottom, n.width -= t.left + t.right; -var a; -for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); -if (a) { -var f = n.width - s; -a.width = f >= 0 ? f : a.width; -} -for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ -top: t.top, -bottom: t.bottom, -width: u.fit ? u.width : null -}); -}, -arrange: function(e, t) { -this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); -}, -arrangeNoWrap: function(e, t) { -var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; -for (n = u, i = 0; s = o[n]; n++) { -i += s.width + s.marginWidth; -if (i > a) break; -} -var f = a - i, l = 0; -if (f > 0) { -var c = u; -for (n = u - 1, r = 0; s = o[n]; n--) { -r += s.width + s.marginWidth; -if (f - r <= 0) { -l = f - r, u = n; -break; -} -} -} -var h, p; -for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { -left: -h -}) : (this.arrangeControl(s, { -left: Math.floor(p) -}), p += h); -}, -arrangeWrap: function(e, t) { -for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { -left: r -}), r += s.width + s.marginWidth; -}, -calcArrangementDifference: function(e, t, n, r) { -var i = Math.abs(e % this.c$.length); -return t[i].left - r[i].left; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// CollapsingArranger.js - -enyo.kind({ -name: "enyo.CollapsingArranger", -kind: "CarouselArranger", -peekWidth: 0, -size: function() { -this.clearLastSize(), this.inherited(arguments); -}, -clearLastSize: function() { -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); -}, -constructor: function() { -this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; -}, -arrange: function(e, t) { -var n = this.container.getPanels(); -for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { -left: i + u * this.peekWidth -}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { -left: i -}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { -left: i - t -}); -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels().length - 1; -return Math.abs(r[i].left - t[i].left); -}, -flowControl: function(e, t) { -this.inherited(arguments); -if (this.container.realtimeFit) { -var n = this.container.getPanels(), r = n.length - 1, i = n[r]; -e == i && this.fitControl(e, t.left); -} -}, -finish: function() { -this.inherited(arguments); -if (!this.container.realtimeFit && this.containerBounds) { -var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; -this.fitControl(r, t[n].left); -} -}, -fitControl: function(e, t) { -e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); -} -}); - -// DockRightArranger.js - -enyo.kind({ -name: "enyo.DockRightArranger", -kind: "Arranger", -basePanel: !1, -overlap: 0, -layoutWidth: 0, -constructor: function() { -this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; -n.width -= t.left + t.right; -var o = n.width, u = e.length; -this.container.transitionPositions = {}; -for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; -for (r = 0; s = e[r]; r++) { -r === 0 && this.container.basePanel && s.setBounds({ -width: o -}), s.setBounds({ -top: t.top, -bottom: t.bottom -}); -for (j = 0; s = e[j]; j++) { -var a; -if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { -if (r !== j) break; -var f = o > this.layoutWidth ? this.overlap : 0; -a = o - e[r].width + f; -} -this.container.transitionPositions[r + "." + j] = a; -} -if (j < u) { -var l = !1; -for (k = r + 1; k < u; k++) { -var f = 0; -if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { -f = e[r].width - this.overlap; -for (i = r; i < k; i++) { -var c = f + e[i + 1].width - this.overlap; -if (!(c < o)) { -f = o; -break; -} -f = c; -} -f = o - f; -} -this.container.transitionPositions[r + "." + k] = f; -} -} -} -}, -arrange: function(e, t) { -var n, r, i = this.container.getPanels(), s = this.container.clamp(t); -for (n = 0; r = i[n]; n++) { -var o = this.container.transitionPositions[n + "." + s]; -this.arrangeControl(r, { -left: o -}); -} -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; -return s; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// OtherArrangers.js - -enyo.kind({ -name: "enyo.LeftRightArranger", -kind: "Arranger", -margin: 40, -axisSize: "width", -offAxisSize: "height", -axisPosition: "left", -constructor: function() { -this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; -for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); -}, -start: function() { -this.inherited(arguments); -var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); -for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); -}, -arrange: function(e, t) { -var n, r, i, s; -if (this.container.getPanels().length == 1) { -s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); -return; -} -var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; -for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; -}, -calcArrangementDifference: function(e, t, n, r) { -if (this.container.getPanels().length == 1) return 0; -var i = Math.abs(e % this.c$.length); -return t[i][this.axisPosition] - r[i][this.axisPosition]; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.TopBottomArranger", -kind: "LeftRightArranger", -dragProp: "ddy", -dragDirectionProp: "yDirection", -canDragProp: "vertical", -axisSize: "height", -offAxisSize: "width", -axisPosition: "top" -}), enyo.kind({ -name: "enyo.SpiralArranger", -kind: "Arranger", -incrementalPoints: !0, -inc: 20, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; -for (var i = 0, s; s = e[i]; i++) s.setBounds({ -width: n, -height: r -}); -}, -arrange: function(e, t) { -var n = this.inc; -for (var r = 0, i = e.length, s; s = e[r]; r++) { -var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; -this.arrangeControl(s, { -left: o, -top: u -}); -} -}, -start: function() { -this.inherited(arguments); -var e = this.getOrderedControls(this.container.toIndex); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.controlWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.GridArranger", -kind: "Arranger", -incrementalPoints: !0, -colWidth: 100, -colHeight: 100, -size: function() { -var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; -for (var r = 0, i; i = e[r]; r++) i.setBounds({ -width: t, -height: n -}); -}, -arrange: function(e, t) { -var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; -for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { -left: n * a, -top: r * o -}); -}, -flowControl: function(e, t) { -this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.colWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// Panels.js - -enyo.kind({ -name: "enyo.Panels", -classes: "enyo-panels", -published: { -index: 0, -draggable: !0, -animate: !0, -wrap: !1, -arrangerKind: "CardArranger", -narrowFit: !0 -}, -events: { -onTransitionStart: "", -onTransitionFinish: "" -}, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onscroll: "domScroll" -}, -tools: [ { -kind: "Animator", -onStep: "step", -onEnd: "completed" -} ], -fraction: 0, -create: function() { -this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); -}, -rendered: function() { -this.inherited(arguments), enyo.makeBubble(this, "scroll"); -}, -domScroll: function(e, t) { -this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); -}, -initComponents: function() { -this.createChrome(this.tools), this.inherited(arguments); -}, -arrangerKindChanged: function() { -this.setLayoutKind(this.arrangerKind); -}, -narrowFitChanged: function() { -this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); -}, -destroy: function() { -this.destroying = !0, this.inherited(arguments); -}, -removeControl: function(e) { -this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); -}, -isPanel: function() { -return !0; -}, -flow: function() { -this.arrangements = [], this.inherited(arguments); -}, -reflow: function() { -this.arrangements = [], this.inherited(arguments), this.refresh(); -}, -getPanels: function() { -var e = this.controlParent || this; -return e.children; -}, -getActive: function() { -var e = this.getPanels(), t = this.index % e.length; -return t < 0 && (t += e.length), e[t]; -}, -getAnimator: function() { -return this.$.animator; -}, -setIndex: function(e) { -this.setPropertyValue("index", e, "indexChanged"); -}, -setIndexDirect: function(e) { -this.setIndex(e), this.completed(); -}, -previous: function() { -this.setIndex(this.index - 1); -}, -next: function() { -this.setIndex(this.index + 1); -}, -clamp: function(e) { -var t = this.getPanels().length - 1; -return this.wrap ? e : Math.max(0, Math.min(e, t)); -}, -indexChanged: function(e) { -this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ -startValue: this.fraction -})) : this.refresh())); -}, -step: function(e) { -this.fraction = e.value, this.stepTransition(); -}, -completed: function() { -this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -dragstart: function(e, t) { -if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; -}, -drag: function(e, t) { -this.dragging && (t.preventDefault(), this.dragTransition(t)); -}, -dragfinish: function(e, t) { -this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); -}, -dragstartTransition: function(e) { -if (!this.$.animator.isAnimating()) { -var t = this.fromIndex = this.index; -this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); -} else this.verifyDragTransition(e); -this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); -}, -dragTransition: function(e) { -var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; -a, this.fraction += u; -var f = this.fraction; -if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; -this.stepTransition(); -}, -dragfinishTransition: function(e) { -this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); -}, -verifyDragTransition: function(e) { -var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); -if (t > 0) { -var i = n; -n = r, r = i; -} -n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; -}, -refresh: function() { -this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -startTransition: function() { -this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); -}, -finishTransition: function() { -this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); -}, -fireTransitionStart: function() { -var e = this.startTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { -fromIndex: this.fromIndex, -toIndex: this.toIndex -}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); -}, -fireTransitionFinish: function() { -var e = this.finishTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { -fromIndex: this.lastIndex, -toIndex: this.index -}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; -}, -stepTransition: function() { -if (this.hasNode()) { -var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); -t -= n; -var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); -this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); -} -}, -fetchArrangement: function(e) { -return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; -}, -readArrangement: function(e) { -var t = []; -for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); -return t; -}, -statics: { -isScreenNarrow: function() { -return enyo.dom.getWindowWidth() <= 800; -}, -lerp: function(e, t, n) { -var r = []; -for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); -return r; -}, -lerpObject: function(e, t, n) { -var r = enyo.clone(e), i, s; -if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); -return r; -} -} -}); - -// Node.js - -enyo.kind({ -name: "enyo.Node", -published: { -expandable: !1, -expanded: !1, -icon: "", -onlyIconExpands: !1, -selected: !1 -}, -style: "padding: 0 0 0 16px;", -content: "Node", -defaultKind: "Node", -classes: "enyo-node", -components: [ { -name: "icon", -kind: "Image", -showing: !1 -}, { -kind: "Control", -name: "caption", -Xtag: "span", -style: "display: inline-block; padding: 4px;", -allowHtml: !0 -}, { -kind: "Control", -name: "extra", -tag: "span", -allowHtml: !0 -} ], -childClient: [ { -kind: "Control", -name: "box", -classes: "enyo-node-box", -Xstyle: "border: 1px solid orange;", -components: [ { -kind: "Control", -name: "client", -classes: "enyo-node-client", -Xstyle: "border: 1px solid lightblue;" -} ] -} ], -handlers: { -ondblclick: "dblclick" -}, -events: { -onNodeTap: "nodeTap", -onNodeDblClick: "nodeDblClick", -onExpand: "nodeExpand", -onDestroyed: "nodeDestroyed" -}, -create: function() { -this.inherited(arguments), this.selectedChanged(), this.iconChanged(); -}, -destroy: function() { -this.doDestroyed(), this.inherited(arguments); -}, -initComponents: function() { -this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); -}, -contentChanged: function() { -this.$.caption.setContent(this.content); -}, -iconChanged: function() { -this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); -}, -selectedChanged: function() { -this.addRemoveClass("enyo-selected", this.selected); -}, -rendered: function() { -this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); -}, -addNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent(n); -this.$.client.render(); -}, -addTextNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent({ -content: n -}); -this.$.client.render(); -}, -tap: function(e, t) { -return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; -}, -dblclick: function(e, t) { -return this.doNodeDblClick(), !0; -}, -toggleExpanded: function() { -this.setExpanded(!this.expanded); -}, -quickCollapse: function() { -this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); -var e = this.$.client.getBounds().height; -this.$.client.setBounds({ -top: -e -}); -}, -_expand: function() { -this.addClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), this.$.client.setBounds({ -top: 0 -}), setTimeout(enyo.bind(this, function() { -this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); -}), 225); -}, -_collapse: function() { -this.removeClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), setTimeout(enyo.bind(this, function() { -this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ -top: -e -}); -}), 25); -}, -expandedChanged: function(e) { -if (!this.expandable) this.expanded = !1; else { -var t = { -expanded: this.expanded -}; -this.doExpand(t), t.wait || this.effectExpanded(); -} -}, -effectExpanded: function() { -this.$.client && (this.expanded ? this._expand() : this._collapse()); -} -}); - -// ImageViewPin.js - -enyo.kind({ -name: "enyo.ImageViewPin", -kind: "enyo.Control", -published: { -highlightAnchorPoint: !1, -anchor: { -top: 0, -left: 0 -}, -position: { -top: 0, -left: 0 -} -}, -style: "position:absolute;z-index:1000;width:0px;height:0px;", -handlers: { -onPositionPin: "reAnchor" -}, -create: function() { -this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); -}, -styleClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); -}, -positionClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); -}, -highlightAnchorPointChanged: function() { -this.addRemoveClass("pinDebug", this.highlightAnchorPoint); -}, -anchorChanged: function() { -var e = null, t = null; -for (t in this.anchor) { -e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); -if (!e) continue; -this.anchor[t + "Coords"] = { -value: e[1], -units: e[2] || "px" -}; -} -}, -reAnchor: function(e, t) { -var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; -this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); -} -}); - -// ImageView.js - -enyo.kind({ -name: "enyo.ImageView", -kind: enyo.Scroller, -touchOverscroll: !1, -thumb: !1, -animate: !0, -verticalDragPropagation: !0, -horizontalDragPropagation: !0, -published: { -scale: "auto", -disableZoom: !1, -src: undefined -}, -events: { -onZoom: "" -}, -touch: !0, -preventDragPropagation: !1, -handlers: { -ondragstart: "dragPropagation" -}, -components: [ { -name: "animator", -kind: "Animator", -onStep: "zoomAnimationStep", -onEnd: "zoomAnimationEnd" -}, { -name: "viewport", -style: "overflow:hidden;min-height:100%;min-width:100%;", -classes: "enyo-fit", -ongesturechange: "gestureTransform", -ongestureend: "saveState", -ontap: "singleTap", -ondblclick: "doubleClick", -onmousewheel: "mousewheel", -components: [ { -kind: "Image", -ondown: "down" -} ] -} ], -create: function() { -this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); -}, -down: function(e, t) { -t.preventDefault(); -}, -dragPropagation: function(e, t) { -var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; -return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); -}, -mousewheel: function(e, t) { -t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; -var n = (this.maxScale - this.minScale) / 10, r = this.scale; -if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); -return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; -}, -srcChanged: function() { -this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); -}, -imageLoaded: function(e) { -this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); -}, -resizeHandler: function() { -this.inherited(arguments), this.$.image.src && this.scaleChanged(); -}, -scaleChanged: function() { -var e = this.hasNode(); -if (e) { -this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; -var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; -this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); -} -this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); -}, -imageError: function(e) { -enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); -}, -alignImage: function() { -if (this.fitAlignment && this.fitAlignment === "center") { -var e = this.getScrollBounds(); -this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); -} -}, -gestureTransform: function(e, t) { -this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); -}, -calcEventLocation: function(e) { -var t = { -x: 0, -y: 0 -}; -if (e && this.hasNode()) { -var n = this.node.getBoundingClientRect(); -t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); -} -return t; -}, -transformImage: function(e) { -this.tapped = !1; -var t = this.imageBounds || this.innerImageBounds(e); -this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px" -}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; -var n, r; -this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); -if (this.canTransform) { -var i = { -scale: e -}; -this.canAccelerate ? i = enyo.mixin({ -translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" -}, i) : i = enyo.mixin({ -translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" -}, i), enyo.dom.transform(this.$.image, i); -} else this.$.image.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px", -left: this.imageBounds.left + "px", -top: this.imageBounds.top + "px" -}); -this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); -}, -limitScale: function(e) { -return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; -}, -innerImageBounds: function(e) { -var t = this.originalWidth * e, n = this.originalHeight * e, r = { -x: 0, -y: 0, -transX: 0, -transY: 0 -}; -return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { -left: r.x + r.transX, -top: r.y + r.transY, -width: t, -height: n, -x: r.x, -y: r.y -}; -}, -saveState: function(e, t) { -var n = this.scale; -this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null; -}, -doubleClick: function(e, t) { -enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); -}, -singleTap: function(e, t) { -setTimeout(enyo.bind(this, function() { -this.tapped = !1; -}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; -}, -smartZoom: function(e, t) { -var n = this.hasNode(), r = this.$.image.hasNode(); -if (n && r && this.hasNode() && !this.disableZoom) { -var i = this.scale; -this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); -if (this.animate) { -var s = { -x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, -y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height -}; -this.$.animator.play({ -duration: 350, -ratioLock: s, -baseScale: i, -deltaScale: this.scale - i -}); -} else this.transformImage(this.scale), this.doZoom({ -scale: this.scale -}); -} -}, -zoomAnimationStep: function(e, t) { -var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; -this.transformImage(n); -}, -zoomAnimationEnd: function(e, t) { -this.doZoom({ -scale: this.scale -}), this.$.animator.ratioLock = undefined; -}, -positionClientControls: function(e) { -this.waterfallDown("onPositionPin", { -scale: e, -bounds: this.imageBounds -}); -} -}); - -// ImageCarousel.js - -enyo.kind({ -name: "enyo.ImageCarousel", -kind: enyo.Panels, -arrangerKind: "enyo.CarouselArranger", -defaultScale: "auto", -disableZoom: !1, -lowMemory: !1, -published: { -images: [] -}, -handlers: { -onTransitionStart: "transitionStart", -onTransitionFinish: "transitionFinish" -}, -create: function() { -this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); -}, -initContainers: function() { -for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ -name: "container" + e, -style: "height:100%; width:100%;" -}), this.$["container" + e].render()); -for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); -this.imageCount = this.images.length; -}, -loadNearby: function() { -var e = this.getBufferRange(); -for (var t in e) this.loadImageView(e[t]); -}, -getBufferRange: function() { -var e = []; -if (this.layout.containerBounds) { -var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; -o = this.index - 1, u = 0, a = n.width * t; -while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; -o = this.index, u = 0, a = n.width * (t + 1); -while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; -} -return e; -}, -reflow: function() { -this.inherited(arguments), this.loadNearby(); -}, -loadImageView: function(e) { -return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ -name: "image" + e, -kind: "ImageView", -scale: this.defaultScale, -disableZoom: this.disableZoom, -src: this.images[e], -verticalDragPropagation: !1, -style: "height:100%; width:100%;" -}, { -owner: this -}), this.$["image" + e].render())), this.$["image" + e]; -}, -setImages: function(e) { -this.setPropertyValue("images", e, "imagesChanged"); -}, -imagesChanged: function() { -this.initContainers(), this.loadNearby(); -}, -indexChanged: function() { -this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); -}, -transitionStart: function(e, t) { -if (t.fromIndex == t.toIndex) return !0; -}, -transitionFinish: function(e, t) { -this.loadNearby(), this.lowMemory && this.cleanupMemory(); -}, -getActiveImage: function() { -return this.getImageByIndex(this.index); -}, -getImageByIndex: function(e) { -return this.$["image" + e] || this.loadImageView(e); -}, -cleanupMemory: function() { -var e = getBufferRange(); -for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); -} -}); - -// Icon.js - -enyo.kind({ -name: "onyx.Icon", -published: { -src: "", -disabled: !1 -}, -classes: "onyx-icon", -create: function() { -this.inherited(arguments), this.src && this.srcChanged(), this.disabledChanged(); -}, -disabledChanged: function() { -this.addRemoveClass("disabled", this.disabled); -}, -srcChanged: function() { -this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); -} -}); - -// Button.js - -enyo.kind({ -name: "onyx.Button", -kind: "enyo.Button", -classes: "onyx-button enyo-unselectable", -create: function() { -enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -} -}); - -// IconButton.js - -enyo.kind({ -name: "onyx.IconButton", -kind: "onyx.Icon", -published: { -active: !1 -}, -classes: "onyx-icon-button", -create: function() { -enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -}, -rendered: function() { -this.inherited(arguments), this.activeChanged(); -}, -tap: function() { -if (this.disabled) return !0; -this.setActive(!0); -}, -activeChanged: function() { -this.bubble("onActivate"); -} -}); - -// Checkbox.js - -enyo.kind({ -name: "onyx.Checkbox", -classes: "onyx-checkbox", -kind: enyo.Checkbox, -tag: "div", -handlers: { -onclick: "" -}, -tap: function(e, t) { -return this.disabled || (this.setChecked(!this.getChecked()), this.bubble("onchange")), !this.disabled; -}, -dragstart: function() {} -}); - -// Drawer.js - -enyo.kind({ -name: "onyx.Drawer", -published: { -open: !0, -orient: "v", -animated: !0 -}, -style: "overflow: hidden; position: relative;", -tools: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorEnd" -}, { -name: "client", -style: "position: relative;", -classes: "enyo-border-box" -} ], -create: function() { -this.inherited(arguments), this.animatedChanged(), this.openChanged(); -}, -initComponents: function() { -this.createChrome(this.tools), this.inherited(arguments); -}, -animatedChanged: function() { -!this.animated && this.hasNode() && this.$.animator.isAnimating() && (this.$.animator.stop(), this.animatorEnd()); -}, -openChanged: function() { -this.$.client.show(); -if (this.hasNode()) if (this.$.animator.isAnimating()) this.$.animator.reverse(); else { -var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left"; -this.applyStyle(t, null); -var r = this.hasNode()[e ? "scrollHeight" : "scrollWidth"]; -this.animated ? this.$.animator.play({ -startValue: this.open ? 0 : r, -endValue: this.open ? r : 0, -dimension: t, -position: n -}) : this.animatorEnd(); -} else this.$.client.setShowing(this.open); -}, -animatorStep: function(e) { -if (this.hasNode()) { -var t = e.dimension; -this.node.style[t] = this.domStyles[t] = e.value + "px"; -} -var n = this.$.client.hasNode(); -if (n) { -var r = e.position, i = this.open ? e.endValue : e.startValue; -n.style[r] = this.$.client.domStyles[r] = e.value - i + "px"; -} -this.container && this.container.resized(); -}, -animatorEnd: function() { -if (!this.open) this.$.client.hide(); else { -this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); -var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left", r = this.$.client.hasNode(); -r && (r.style[n] = this.$.client.domStyles[n] = null), this.node && (this.node.style[t] = this.domStyles[t] = null); -} -this.container && this.container.resized(); -} -}); - -// Grabber.js - -enyo.kind({ -name: "onyx.Grabber", -classes: "onyx-grabber" -}); - -// Groupbox.js - -enyo.kind({ -name: "onyx.Groupbox", -classes: "onyx-groupbox" -}), enyo.kind({ -name: "onyx.GroupboxHeader", -classes: "onyx-groupbox-header" -}); - -// Input.js - -enyo.kind({ -name: "onyx.Input", -kind: "enyo.Input", -classes: "onyx-input" -}); - -// Popup.js - -enyo.kind({ -name: "onyx.Popup", -kind: "Popup", -classes: "onyx-popup", -published: { -scrimWhenModal: !0, -scrim: !1, -scrimClassName: "" -}, -statics: { -count: 0 -}, -defaultZ: 120, -showingChanged: function() { -this.showing ? (onyx.Popup.count++, this.applyZIndex()) : onyx.Popup.count > 0 && onyx.Popup.count--, this.showHideScrim(this.showing), this.inherited(arguments); -}, -showHideScrim: function(e) { -if (this.floating && (this.scrim || this.modal && this.scrimWhenModal)) { -var t = this.getScrim(); -if (e) { -var n = this.getScrimZIndex(); -this._scrimZ = n, t.showAtZIndex(n); -} else t.hideAtZIndex(this._scrimZ); -enyo.call(t, "addRemoveClass", [ this.scrimClassName, t.showing ]); -} -}, -getScrimZIndex: function() { -return this.findZIndex() - 1; -}, -getScrim: function() { -return this.modal && this.scrimWhenModal && !this.scrim ? onyx.scrimTransparent.make() : onyx.scrim.make(); -}, -applyZIndex: function() { -this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1, this.applyStyle("z-index", this._zIndex); -}, -findZIndex: function() { -var e = this.defaultZ; -return this._zIndex ? e = this._zIndex : this.hasNode() && (e = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || e), this._zIndex = e; -} -}); - -// TextArea.js - -enyo.kind({ -name: "onyx.TextArea", -kind: "enyo.TextArea", -classes: "onyx-textarea" -}); - -// RichText.js - -enyo.kind({ -name: "onyx.RichText", -kind: "enyo.RichText", -classes: "onyx-richtext" -}); - -// InputDecorator.js - -enyo.kind({ -name: "onyx.InputDecorator", -kind: "enyo.ToolDecorator", -tag: "label", -classes: "onyx-input-decorator", -published: { -alwaysLooksFocused: !1 -}, -handlers: { -onDisabledChange: "disabledChange", -onfocus: "receiveFocus", -onblur: "receiveBlur" -}, -create: function() { -this.inherited(arguments), this.updateFocus(!1); -}, -alwaysLooksFocusedChanged: function(e) { -this.updateFocus(this.focus); -}, -updateFocus: function(e) { -this.focused = e, this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); -}, -receiveFocus: function() { -this.updateFocus(!0); -}, -receiveBlur: function() { -this.updateFocus(!1); -}, -disabledChange: function(e, t) { -this.addRemoveClass("onyx-disabled", t.originator.disabled); -} -}); - -// Tooltip.js - -enyo.kind({ -name: "onyx.Tooltip", -kind: "onyx.Popup", -classes: "onyx-tooltip below left-arrow", -autoDismiss: !1, -showDelay: 500, -defaultLeft: -6, -handlers: { -onRequestShowTooltip: "requestShow", -onRequestHideTooltip: "requestHide" -}, -requestShow: function() { -return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; -}, -cancelShow: function() { -clearTimeout(this.showJob); -}, -requestHide: function() { -return this.cancelShow(), this.inherited(arguments); -}, -showingChanged: function() { -this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -adjustPosition: function(e) { -if (this.showing && this.hasNode()) { -var t = this.node.getBoundingClientRect(); -t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ -"margin-left": -t.width, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); -} -}, -resizeHandler: function() { -this.applyPosition({ -"margin-left": this.defaultLeft, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); -} -}); - -// TooltipDecorator.js - -enyo.kind({ -name: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator", -handlers: { -onenter: "enter", -onleave: "leave" -}, -enter: function() { -this.requestShowTooltip(); -}, -leave: function() { -this.requestHideTooltip(); -}, -tap: function() { -this.requestHideTooltip(); -}, -requestShowTooltip: function() { -this.waterfallDown("onRequestShowTooltip"); -}, -requestHideTooltip: function() { -this.waterfallDown("onRequestHideTooltip"); -} -}); - -// MenuDecorator.js - -enyo.kind({ -name: "onyx.MenuDecorator", -kind: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator enyo-unselectable", -handlers: { -onActivate: "activated", -onHide: "menuHidden" -}, -activated: function(e, t) { -this.requestHideTooltip(), t.originator.active && (this.menuActive = !0, this.activator = t.originator, this.activator.addClass("active"), this.requestShowMenu()); -}, -requestShowMenu: function() { -this.waterfallDown("onRequestShowMenu", { -activator: this.activator -}); -}, -requestHideMenu: function() { -this.waterfallDown("onRequestHideMenu"); -}, -menuHidden: function() { -this.menuActive = !1, this.activator && (this.activator.setActive(!1), this.activator.removeClass("active")); -}, -enter: function(e) { -this.menuActive || this.inherited(arguments); -}, -leave: function(e, t) { -this.menuActive || this.inherited(arguments); -} -}); - -// Menu.js - -enyo.kind({ -name: "onyx.Menu", -kind: "onyx.Popup", -modal: !0, -defaultKind: "onyx.MenuItem", -classes: "onyx-menu", -published: { -maxHeight: 200, -scrolling: !0 -}, -handlers: { -onActivate: "itemActivated", -onRequestShowMenu: "requestMenuShow", -onRequestHideMenu: "requestHide" -}, -childComponents: [ { -name: "client", -kind: "enyo.Scroller", -strategyKind: "TouchScrollStrategy" -} ], -showOnTop: !1, -scrollerName: "client", -create: function() { -this.inherited(arguments), this.maxHeightChanged(); -}, -initComponents: function() { -this.scrolling && this.createComponents(this.childComponents, { -isChrome: !0 -}), this.inherited(arguments); -}, -getScroller: function() { -return this.$[this.scrollerName]; -}, -maxHeightChanged: function() { -this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); -}, -itemActivated: function(e, t) { -return t.originator.setActive(!1), !0; -}, -showingChanged: function() { -this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(!0); -}, -requestMenuShow: function(e, t) { -if (this.floating) { -var n = t.activator.hasNode(); -if (n) { -var r = this.activatorOffset = this.getPageOffset(n); -this.applyPosition({ -top: r.top + (this.showOnTop ? 0 : r.height), -left: r.left, -width: r.width -}); -} -} -return this.show(), !0; -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -getPageOffset: function(e) { -var t = e.getBoundingClientRect(), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; -return { -top: t.top + n, -left: t.left + r, -height: i, -width: s -}; -}, -adjustPosition: function() { -if (this.showing && this.hasNode()) { -this.scrolling && !this.showOnTop && this.getScroller().setMaxHeight(this.maxHeight + "px"), this.removeClass("onyx-menu-up"), this.floating || this.applyPosition({ -left: "auto" -}); -var e = this.node.getBoundingClientRect(), t = e.height === undefined ? e.bottom - e.top : e.height, n = window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight, r = window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; -this.menuUp = e.top + t > n && n - e.bottom < e.top - t, this.addRemoveClass("onyx-menu-up", this.menuUp); -if (this.floating) { -var i = this.activatorOffset; -this.menuUp ? this.applyPosition({ -top: i.top - t + (this.showOnTop ? i.height : 0), -bottom: "auto" -}) : e.top < i.top && i.top + (this.showOnTop ? 0 : i.height) + t < n && this.applyPosition({ -top: i.top + (this.showOnTop ? 0 : i.height), -bottom: "auto" -}); -} -e.right > r && (this.floating ? this.applyPosition({ -left: r - e.width -}) : this.applyPosition({ -left: -(e.right - r) -})), e.left < 0 && (this.floating ? this.applyPosition({ -left: 0, -right: "auto" -}) : this.getComputedStyleValue("right") == "auto" ? this.applyPosition({ -left: -e.left -}) : this.applyPosition({ -right: e.left -})); -if (this.scrolling && !this.showOnTop) { -e = this.node.getBoundingClientRect(); -var s; -this.menuUp ? s = this.maxHeight < e.bottom ? this.maxHeight : e.bottom : s = e.top + this.maxHeight < n ? this.maxHeight : n - e.top, this.getScroller().setMaxHeight(s + "px"); -} -} -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -}, -requestHide: function() { -this.setShowing(!1); -} -}); - -// MenuItem.js - -enyo.kind({ -name: "onyx.MenuItem", -kind: "enyo.Button", -events: { -onSelect: "", -onItemContentChange: "" -}, -classes: "onyx-menu-item", -tag: "div", -create: function() { -this.inherited(arguments), this.active && this.bubble("onActivate"); -}, -tap: function(e) { -this.inherited(arguments), this.bubble("onRequestHideMenu"), this.doSelect({ -selected: this, -content: this.content -}); -}, -contentChanged: function(e) { -this.inherited(arguments), this.doItemContentChange({ -content: this.content -}); -} -}); - -// PickerDecorator.js - -enyo.kind({ -name: "onyx.PickerDecorator", -kind: "onyx.MenuDecorator", -classes: "onyx-picker-decorator", -defaultKind: "onyx.PickerButton", -handlers: { -onChange: "change" -}, -change: function(e, t) { -this.waterfallDown("onChange", t); -} -}); - -// PickerButton.js - -enyo.kind({ -name: "onyx.PickerButton", -kind: "onyx.Button", -handlers: { -onChange: "change" -}, -change: function(e, t) { -t.content !== undefined && this.setContent(t.content); -} -}); - -// Picker.js - -enyo.kind({ -name: "onyx.Picker", -kind: "onyx.Menu", -classes: "onyx-picker enyo-unselectable", -published: { -selected: null -}, -events: { -onChange: "" -}, -handlers: { -onItemContentChange: "itemContentChange" -}, -floating: !0, -showOnTop: !0, -initComponents: function() { -this.setScrolling(!0), this.inherited(arguments); -}, -showingChanged: function() { -this.getScroller().setShowing(this.showing), this.inherited(arguments), this.showing && this.selected && this.scrollToSelected(); -}, -scrollToSelected: function() { -this.getScroller().scrollToControl(this.selected, !this.menuUp); -}, -itemActivated: function(e, t) { -return this.processActivatedItem(t.originator), this.inherited(arguments); -}, -processActivatedItem: function(e) { -e.active && this.setSelected(e); -}, -selectedChanged: function(e) { -e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ -selected: this.selected, -content: this.selected.content -})); -}, -itemContentChange: function(e, t) { -t.originator == this.selected && this.doChange({ -selected: this.selected, -content: this.selected.content -}); -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -} -}); - -// FlyweightPicker.js - -enyo.kind({ -name: "onyx.FlyweightPicker", -kind: "onyx.Picker", -classes: "onyx-flyweight-picker", -published: { -count: 0 -}, -events: { -onSetupItem: "", -onSelect: "" -}, -handlers: { -onSelect: "itemSelect" -}, -components: [ { -name: "scroller", -kind: "enyo.Scroller", -strategyKind: "TouchScrollStrategy", -components: [ { -name: "flyweight", -kind: "FlyweightRepeater", -noSelect: !0, -ontap: "itemTap" -} ] -} ], -scrollerName: "scroller", -initComponents: function() { -this.controlParentName = "flyweight", this.inherited(arguments), this.$.flyweight.$.client.children[0].setActive(!0); -}, -create: function() { -this.inherited(arguments), this.countChanged(); -}, -rendered: function() { -this.inherited(arguments), this.selectedChanged(); -}, -scrollToSelected: function() { -var e = this.$.flyweight.fetchRowNode(this.selected); -this.getScroller().scrollToNode(e, !this.menuUp); -}, -countChanged: function() { -this.$.flyweight.count = this.count; -}, -processActivatedItem: function(e) { -this.item = e; -}, -selectedChanged: function(e) { -if (!this.item) return; -e != null && (this.item.removeClass("selected"), this.$.flyweight.renderRow(e)); -var t; -this.selected != null && (this.item.addClass("selected"), this.$.flyweight.renderRow(this.selected), this.item.removeClass("selected"), t = this.$.flyweight.fetchRowNode(this.selected)), this.doChange({ -selected: this.selected, -content: t && t.textContent || this.item.content -}); -}, -itemTap: function(e, t) { -this.setSelected(t.rowIndex), this.doSelect({ -selected: this.item, -content: this.item.content -}); -}, -itemSelect: function(e, t) { -if (t.originator != this) return !0; -} -}); - -// DatePicker.js - -enyo.kind({ -name: "onyx.DatePicker", -classes: "onyx-toolbar-inline", -published: { -disabled: !1, -locale: "en_us", -dayHidden: !1, -monthHidden: !1, -yearHidden: !1, -minYear: 1900, -maxYear: 2099, -value: null -}, -events: { -onSelect: "" -}, -create: function() { -this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); -}, -initDefaults: function() { -var e = [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; -enyo.g11n && (this._tf = new enyo.g11n.Fmts({ -locale: this.locale -}), e = this._tf.getMonthFields()), this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : "mdy"), this.dayHiddenChanged(), this.monthHiddenChanged(), this.yearHiddenChanged(); -var t = this.value = this.value || new Date; -for (var n = 0, r; r = e[n]; n++) this.$.monthPicker.createComponent({ -content: r, -value: n, -active: n == t.getMonth() -}); -var i = t.getFullYear(); -this.$.yearPicker.setSelected(i - this.minYear); -for (n = 1; n <= this.monthLength(t.getYear(), t.getMonth()); n++) this.$.dayPicker.createComponent({ -content: n, -value: n, -active: n == t.getDate() -}); -}, -monthLength: function(e, t) { -return 32 - (new Date(e, t, 32)).getDate(); -}, -setupYear: function(e, t) { -this.$.year.setContent(this.minYear + t.index); -}, -setupPickers: function(e) { -var t = e.split(""), n, r, i; -for (r = 0, i = t.length; r < i; r++) { -n = t[r]; -switch (n) { -case "d": -this.createDay(); -break; -case "m": -this.createMonth(); -break; -case "y": -this.createYear(); -break; -default: -} -} -}, -createYear: function() { -var e = this.maxYear - this.minYear; -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateYear", -components: [ { -classes: "onyx-datepicker-year", -name: "yearPickerButton", -disabled: this.disabled -}, { -name: "yearPicker", -kind: "onyx.FlyweightPicker", -count: ++e, -onSetupItem: "setupYear", -components: [ { -name: "year" -} ] -} ] -}); -}, -createMonth: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateMonth", -components: [ { -classes: "onyx-datepicker-month", -name: "monthPickerButton", -disabled: this.disabled -}, { -name: "monthPicker", -kind: "onyx.Picker" -} ] -}); -}, -createDay: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateDay", -components: [ { -classes: "onyx-datepicker-day", -name: "dayPickerButton", -disabled: this.disabled -}, { -name: "dayPicker", -kind: "onyx.Picker" -} ] -}); -}, -localeChanged: function() { -this.refresh(); -}, -dayHiddenChanged: function() { -this.$.dayPicker.getParent().setShowing(this.dayHidden ? !1 : !0); -}, -monthHiddenChanged: function() { -this.$.monthPicker.getParent().setShowing(this.monthHidden ? !1 : !0); -}, -yearHiddenChanged: function() { -this.$.yearPicker.getParent().setShowing(this.yearHidden ? !1 : !0); -}, -minYearChanged: function() { -this.refresh(); -}, -maxYearChanged: function() { -this.refresh(); -}, -valueChanged: function() { -this.refresh(); -}, -disabledChanged: function() { -this.$.yearPickerButton.setDisabled(this.disabled), this.$.monthPickerButton.setDisabled(this.disabled), this.$.dayPickerButton.setDisabled(this.disabled); -}, -updateDay: function(e, t) { -var n = this.calcDate(this.value.getFullYear(), this.value.getMonth(), t.selected.value); -return this.doSelect({ -name: this.name, -value: n -}), this.setValue(n), !0; -}, -updateMonth: function(e, t) { -var n = this.calcDate(this.value.getFullYear(), t.selected.value, this.value.getDate()); -return this.doSelect({ -name: this.name, -value: n -}), this.setValue(n), !0; -}, -updateYear: function(e, t) { -if (t.originator.selected != -1) { -var n = this.calcDate(this.minYear + t.originator.selected, this.value.getMonth(), this.value.getDate()); -this.doSelect({ -name: this.name, -value: n -}), this.setValue(n); -} -return !0; -}, -calcDate: function(e, t, n) { -return new Date(e, t, n, this.value.getHours(), this.value.getMinutes(), this.value.getSeconds(), this.value.getMilliseconds()); -}, -refresh: function() { -this.destroyClientControls(), this.initDefaults(), this.render(); -} -}); - -// TimePicker.js - -enyo.kind({ -name: "onyx.TimePicker", -classes: "onyx-toolbar-inline", -published: { -disabled: !1, -locale: "en_us", -is24HrMode: null, -value: null -}, -events: { -onSelect: "" -}, -create: function() { -this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); -}, -initDefaults: function() { -var e = "AM", t = "PM"; -this.is24HrMode == null && (this.is24HrMode = !1), enyo.g11n && (this._tf = new enyo.g11n.Fmts({ -locale: this.locale -}), e = this._tf.getAmCaption(), t = this._tf.getPmCaption(), this.is24HrMode == null && (this.is24HrMode = !this._tf.isAmPm())), this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : "hma"); -var n = this.value = this.value || new Date, r; -if (!this.is24HrMode) { -var i = n.getHours(); -i = i === 0 ? 12 : i; -for (r = 1; r <= 12; r++) this.$.hourPicker.createComponent({ -content: r, -value: r, -active: r == (i > 12 ? i % 12 : i) -}); -} else for (r = 0; r < 24; r++) this.$.hourPicker.createComponent({ -content: r, -value: r, -active: r == n.getHours() -}); -for (r = 0; r <= 59; r++) this.$.minutePicker.createComponent({ -content: r < 10 ? "0" + r : r, -value: r, -active: r == n.getMinutes() -}); -n.getHours() >= 12 ? this.$.ampmPicker.createComponents([ { -content: e -}, { -content: t, -active: !0 -} ]) : this.$.ampmPicker.createComponents([ { -content: e, -active: !0 -}, { -content: t -} ]), this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); -}, -setupPickers: function(e) { -var t = e.split(""), n, r, i; -for (r = 0, i = t.length; r < i; r++) { -n = t[r]; -switch (n) { -case "h": -this.createHour(); -break; -case "m": -this.createMinute(); -break; -case "a": -this.createAmPm(); -break; -default: -} -} -}, -createHour: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateHour", -components: [ { -classes: "onyx-timepicker-hour", -name: "hourPickerButton", -disabled: this.disabled -}, { -name: "hourPicker", -kind: "onyx.Picker" -} ] -}); -}, -createMinute: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateMinute", -components: [ { -classes: "onyx-timepicker-minute", -name: "minutePickerButton", -disabled: this.disabled -}, { -name: "minutePicker", -kind: "onyx.Picker" -} ] -}); -}, -createAmPm: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateAmPm", -components: [ { -classes: "onyx-timepicker-ampm", -name: "ampmPickerButton", -disabled: this.disabled -}, { -name: "ampmPicker", -kind: "onyx.Picker" -} ] -}); -}, -disabledChanged: function() { -this.$.hourPickerButton.setDisabled(this.disabled), this.$.minutePickerButton.setDisabled(this.disabled), this.$.ampmPickerButton.setDisabled(this.disabled); -}, -localeChanged: function() { -this.is24HrMode = null, this.refresh(); -}, -is24HrModeChanged: function() { -this.refresh(); -}, -valueChanged: function() { -this.refresh(); -}, -updateHour: function(e, t) { -var n = t.selected.value; -if (!this.is24HrMode) { -var r = this.$.ampmPicker.getParent().controlAtIndex(0).content; -n = n + (n == 12 ? -12 : 0) + (this.isAm(r) ? 0 : 12); -} -return this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -updateMinute: function(e, t) { -return this.value = this.calcTime(this.value.getHours(), t.selected.value), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -updateAmPm: function(e, t) { -var n = this.value.getHours(); -return this.is24HrMode || (n += n > 11 ? this.isAm(t.content) ? -12 : 0 : this.isAm(t.content) ? 0 : 12), this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -calcTime: function(e, t) { -return new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), e, t, this.value.getSeconds(), this.value.getMilliseconds()); -}, -isAm: function(e) { -var t, n, r; -try { -t = this._tf.getAmCaption(), n = this._tf.getPmCaption(); -} catch (i) { -t = "AM", n = "PM"; -} -return e == t ? !0 : !1; -}, -refresh: function() { -this.destroyClientControls(), this.initDefaults(), this.render(); -} -}); - -// RadioButton.js - -enyo.kind({ -name: "onyx.RadioButton", -kind: "Button", -classes: "onyx-radiobutton" -}); - -// RadioGroup.js - -enyo.kind({ -name: "onyx.RadioGroup", -kind: "Group", -defaultKind: "onyx.RadioButton", -highlander: !0 -}); - -// ToggleButton.js - -enyo.kind({ -name: "onyx.ToggleButton", -classes: "onyx-toggle-button", -published: { -active: !1, -value: !1, -onContent: "On", -offContent: "Off", -disabled: !1 -}, -events: { -onChange: "" -}, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -components: [ { -name: "contentOn", -classes: "onyx-toggle-content on" -}, { -name: "contentOff", -classes: "onyx-toggle-content off" -}, { -classes: "onyx-toggle-button-knob" -} ], -create: function() { -this.inherited(arguments), this.value = Boolean(this.value || this.active), this.onContentChanged(), this.offContentChanged(), this.disabledChanged(); -}, -rendered: function() { -this.inherited(arguments), this.updateVisualState(); -}, -updateVisualState: function() { -this.addRemoveClass("off", !this.value), this.$.contentOn.setShowing(this.value), this.$.contentOff.setShowing(!this.value), this.setActive(this.value); -}, -valueChanged: function() { -this.updateVisualState(), this.doChange({ -value: this.value -}); -}, -activeChanged: function() { -this.setValue(this.active), this.bubble("onActivate"); -}, -onContentChanged: function() { -this.$.contentOn.setContent(this.onContent || ""), this.$.contentOn.addRemoveClass("empty", !this.onContent); -}, -offContentChanged: function() { -this.$.contentOff.setContent(this.offContent || ""), this.$.contentOff.addRemoveClass("empty", !this.onContent); -}, -disabledChanged: function() { -this.addRemoveClass("disabled", this.disabled); -}, -updateValue: function(e) { -this.disabled || this.setValue(e); -}, -tap: function() { -this.updateValue(!this.value); -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, this.dragged = !1, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = t.dx; -return Math.abs(n) > 10 && (this.updateValue(n > 0), this.dragged = !0), !0; -} -}, -dragfinish: function(e, t) { -this.dragging = !1, this.dragged && t.preventTap(); -} -}); - -// ToggleIconButton.js - -enyo.kind({ -name: "onyx.ToggleIconButton", -kind: "onyx.Icon", -published: { -active: !1, -value: !1 -}, -events: { -onChange: "" -}, -classes: "onyx-icon-button onyx-icon-toggle", -activeChanged: function() { -this.addRemoveClass("active", this.value), this.bubble("onActivate"); -}, -updateValue: function(e) { -this.disabled || (this.setValue(e), this.doChange({ -value: this.value -})); -}, -tap: function() { -this.updateValue(!this.value); -}, -valueChanged: function() { -this.setActive(this.value); -}, -create: function() { -this.inherited(arguments), this.value = Boolean(this.value || this.active); -}, -rendered: function() { -this.inherited(arguments), this.valueChanged(), this.removeClass("onyx-icon"); -} -}); - -// Toolbar.js - -enyo.kind({ -name: "onyx.Toolbar", -classes: "onyx onyx-toolbar onyx-toolbar-inline", -create: function() { -this.inherited(arguments), this.hasClass("onyx-menu-toolbar") && enyo.platform.android >= 4 && this.applyStyle("position", "static"); -} -}); - -// Tooltip.js - -enyo.kind({ -name: "onyx.Tooltip", -kind: "onyx.Popup", -classes: "onyx-tooltip below left-arrow", -autoDismiss: !1, -showDelay: 500, -defaultLeft: -6, -handlers: { -onRequestShowTooltip: "requestShow", -onRequestHideTooltip: "requestHide" -}, -requestShow: function() { -return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; -}, -cancelShow: function() { -clearTimeout(this.showJob); -}, -requestHide: function() { -return this.cancelShow(), this.inherited(arguments); -}, -showingChanged: function() { -this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -adjustPosition: function(e) { -if (this.showing && this.hasNode()) { -var t = this.node.getBoundingClientRect(); -t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ -"margin-left": -t.width, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); -} -}, -resizeHandler: function() { -this.applyPosition({ -"margin-left": this.defaultLeft, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); -} -}); - -// TooltipDecorator.js - -enyo.kind({ -name: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator", -handlers: { -onenter: "enter", -onleave: "leave" -}, -enter: function() { -this.requestShowTooltip(); -}, -leave: function() { -this.requestHideTooltip(); -}, -tap: function() { -this.requestHideTooltip(); -}, -requestShowTooltip: function() { -this.waterfallDown("onRequestShowTooltip"); -}, -requestHideTooltip: function() { -this.waterfallDown("onRequestHideTooltip"); -} -}); - -// ProgressBar.js - -enyo.kind({ -name: "onyx.ProgressBar", -classes: "onyx-progress-bar", -published: { -progress: 0, -min: 0, -max: 100, -barClasses: "", -showStripes: !0, -animateStripes: !0, -increment: 0 -}, -events: { -onAnimateProgressFinish: "" -}, -components: [ { -name: "progressAnimator", -kind: "Animator", -onStep: "progressAnimatorStep", -onEnd: "progressAnimatorComplete" -}, { -name: "bar", -classes: "onyx-progress-bar-bar" -} ], -create: function() { -this.inherited(arguments), this.progressChanged(), this.barClassesChanged(), this.showStripesChanged(), this.animateStripesChanged(); -}, -barClassesChanged: function(e) { -this.$.bar.removeClass(e), this.$.bar.addClass(this.barClasses); -}, -showStripesChanged: function() { -this.$.bar.addRemoveClass("striped", this.showStripes); -}, -animateStripesChanged: function() { -this.$.bar.addRemoveClass("animated", this.animateStripes); -}, -progressChanged: function() { -this.progress = this.clampValue(this.min, this.max, this.progress); -var e = this.calcPercent(this.progress); -this.updateBarPosition(e); -}, -calcIncrement: function(e) { -return Math.round(e / this.increment) * this.increment; -}, -clampValue: function(e, t, n) { -return Math.max(e, Math.min(n, t)); -}, -calcRatio: function(e) { -return (e - this.min) / (this.max - this.min); -}, -calcPercent: function(e) { -return this.calcRatio(e) * 100; -}, -updateBarPosition: function(e) { -this.$.bar.applyStyle("width", e + "%"); -}, -animateProgressTo: function(e) { -this.$.progressAnimator.play({ -startValue: this.progress, -endValue: e, -node: this.hasNode() -}); -}, -progressAnimatorStep: function(e) { -return this.setProgress(e.value), !0; -}, -progressAnimatorComplete: function(e) { -return this.doAnimateProgressFinish(e), !0; -} -}); - -// ProgressButton.js - -enyo.kind({ -name: "onyx.ProgressButton", -kind: "onyx.ProgressBar", -classes: "onyx-progress-button", -events: { -onCancel: "" -}, -components: [ { -name: "progressAnimator", -kind: "Animator", -onStep: "progressAnimatorStep", -onEnd: "progressAnimatorComplete" -}, { -name: "bar", -classes: "onyx-progress-bar-bar onyx-progress-button-bar" -}, { -name: "client", -classes: "onyx-progress-button-client" -}, { -kind: "onyx.Icon", -src: "$lib/onyx/images/progress-button-cancel.png", -classes: "onyx-progress-button-icon", -ontap: "cancelTap" -} ], -cancelTap: function() { -this.doCancel(); -} -}); - -// Scrim.js - -enyo.kind({ -name: "onyx.Scrim", -showing: !1, -classes: "onyx-scrim enyo-fit", -floating: !1, -create: function() { -this.inherited(arguments), this.zStack = [], this.floating && this.setParent(enyo.floatingLayer); -}, -showingChanged: function() { -this.floating && this.showing && !this.hasNode() && this.render(), this.inherited(arguments); -}, -addZIndex: function(e) { -enyo.indexOf(e, this.zStack) < 0 && this.zStack.push(e); -}, -removeZIndex: function(e) { -enyo.remove(e, this.zStack); -}, -showAtZIndex: function(e) { -this.addZIndex(e), e !== undefined && this.setZIndex(e), this.show(); -}, -hideAtZIndex: function(e) { -this.removeZIndex(e); -if (!this.zStack.length) this.hide(); else { -var t = this.zStack[this.zStack.length - 1]; -this.setZIndex(t); -} -}, -setZIndex: function(e) { -this.zIndex = e, this.applyStyle("z-index", e); -}, -make: function() { -return this; -} -}), enyo.kind({ -name: "onyx.scrimSingleton", -kind: null, -constructor: function(e, t) { -this.instanceName = e, enyo.setObject(this.instanceName, this), this.props = t || {}; -}, -make: function() { -var e = new onyx.Scrim(this.props); -return enyo.setObject(this.instanceName, e), e; -}, -showAtZIndex: function(e) { -var t = this.make(); -t.showAtZIndex(e); -}, -hideAtZIndex: enyo.nop, -show: function() { -var e = this.make(); -e.show(); -} -}), new onyx.scrimSingleton("onyx.scrim", { -floating: !0, -classes: "onyx-scrim-translucent" -}), new onyx.scrimSingleton("onyx.scrimTransparent", { -floating: !0, -classes: "onyx-scrim-transparent" -}); - -// Slider.js - -enyo.kind({ -name: "onyx.Slider", -kind: "onyx.ProgressBar", -classes: "onyx-slider", -published: { -value: 0, -lockBar: !0, -tappable: !0 -}, -events: { -onChange: "", -onChanging: "", -onAnimateFinish: "" -}, -showStripes: !1, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -moreComponents: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorComplete" -}, { -classes: "onyx-slider-taparea" -}, { -name: "knob", -classes: "onyx-slider-knob" -} ], -create: function() { -this.inherited(arguments), enyo.platform.firefoxOS && (this.moreComponents[2].ondown = "down", this.moreComponents[2].onleave = "leave"), this.createComponents(this.moreComponents), this.valueChanged(); -}, -valueChanged: function() { -this.value = this.clampValue(this.min, this.max, this.value); -var e = this.calcPercent(this.value); -this.updateKnobPosition(e), this.lockBar && this.setProgress(this.value); -}, -updateKnobPosition: function(e) { -this.$.knob.applyStyle("left", e + "%"); -}, -calcKnobPosition: function(e) { -var t = e.clientX - this.hasNode().getBoundingClientRect().left; -return t / this.getBounds().width * (this.max - this.min) + this.min; -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = this.calcKnobPosition(t); -return n = this.increment ? this.calcIncrement(n) : n, this.setValue(n), this.doChanging({ -value: this.value -}), !0; -} -}, -dragfinish: function(e, t) { -return this.dragging = !1, t.preventTap(), this.doChange({ -value: this.value -}), !0; -}, -tap: function(e, t) { -if (this.tappable) { -var n = this.calcKnobPosition(t); -return n = this.increment ? this.calcIncrement(n) : n, this.tapped = !0, this.animateTo(n), !0; -} -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -}, -animateTo: function(e) { -this.$.animator.play({ -startValue: this.value, -endValue: e, -node: this.hasNode() -}); -}, -animatorStep: function(e) { -return this.setValue(e.value), !0; -}, -animatorComplete: function(e) { -return this.tapped && (this.tapped = !1, this.doChange({ -value: this.value -})), this.doAnimateFinish(e), !0; -} -}); - -// RangeSlider.js - -enyo.kind({ -name: "onyx.RangeSlider", -kind: "onyx.ProgressBar", -classes: "onyx-slider", -published: { -rangeMin: 0, -rangeMax: 100, -rangeStart: 0, -rangeEnd: 100, -beginValue: 0, -endValue: 0 -}, -events: { -onChange: "", -onChanging: "" -}, -showStripes: !1, -showLabels: !1, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -ondown: "down" -}, -moreComponents: [ { -name: "startKnob", -classes: "onyx-slider-knob" -}, { -name: "endKnob", -classes: "onyx-slider-knob onyx-range-slider-knob" -} ], -create: function() { -this.inherited(arguments), this.createComponents(this.moreComponents), this.initControls(); -}, -rendered: function() { -this.inherited(arguments); -var e = this.calcPercent(this.beginValue); -this.updateBarPosition(e); -}, -initControls: function() { -this.$.bar.applyStyle("position", "relative"), this.refreshRangeSlider(), this.showLabels && (this.$.startKnob.createComponent({ -name: "startLabel", -kind: "onyx.RangeSliderKnobLabel" -}), this.$.endKnob.createComponent({ -name: "endLabel", -kind: "onyx.RangeSliderKnobLabel" -})); -}, -refreshRangeSlider: function() { -this.beginValue = this.calcKnobPercent(this.rangeStart), this.endValue = this.calcKnobPercent(this.rangeEnd), this.beginValueChanged(), this.endValueChanged(); -}, -calcKnobRatio: function(e) { -return (e - this.rangeMin) / (this.rangeMax - this.rangeMin); -}, -calcKnobPercent: function(e) { -return this.calcKnobRatio(e) * 100; -}, -beginValueChanged: function(e) { -if (e === undefined) { -var t = this.calcPercent(this.beginValue); -this.updateKnobPosition(t, this.$.startKnob); -} -}, -endValueChanged: function(e) { -if (e === undefined) { -var t = this.calcPercent(this.endValue); -this.updateKnobPosition(t, this.$.endKnob); -} -}, -calcKnobPosition: function(e) { -var t = e.clientX - this.hasNode().getBoundingClientRect().left; -return t / this.getBounds().width * (this.max - this.min) + this.min; -}, -updateKnobPosition: function(e, t) { -t.applyStyle("left", e + "%"), this.updateBarPosition(); -}, -updateBarPosition: function() { -if (this.$.startKnob !== undefined && this.$.endKnob !== undefined) { -var e = this.calcKnobPercent(this.rangeStart), t = this.calcKnobPercent(this.rangeEnd) - e; -this.$.bar.applyStyle("left", e + "%"), this.$.bar.applyStyle("width", t + "%"); -} -}, -calcRangeRatio: function(e) { -return e / 100 * (this.rangeMax - this.rangeMin) + this.rangeMin - this.increment / 2; -}, -swapZIndex: function(e) { -e === "startKnob" ? (this.$.startKnob.applyStyle("z-index", 1), this.$.endKnob.applyStyle("z-index", 0)) : e === "endKnob" && (this.$.startKnob.applyStyle("z-index", 0), this.$.endKnob.applyStyle("z-index", 1)); -}, -down: function(e, t) { -this.swapZIndex(e.name); -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = this.calcKnobPosition(t), r, i, s; -if (e.name === "startKnob" && n >= 0) { -if (!(n <= this.endValue && t.xDirection === -1 || n <= this.endValue)) return this.drag(this.$.endKnob, t); -this.setBeginValue(n), r = this.calcRangeRatio(this.beginValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.startKnob), this.setRangeStart(i), this.doChanging({ -value: i -}); -} else if (e.name === "endKnob" && n <= 100) { -if (!(n >= this.beginValue && t.xDirection === 1 || n >= this.beginValue)) return this.drag(this.$.startKnob, t); -this.setEndValue(n), r = this.calcRangeRatio(this.endValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.endKnob), this.setRangeEnd(i), this.doChanging({ -value: i -}); -} -return !0; -} -}, -dragfinish: function(e, t) { -this.dragging = !1, t.preventTap(); -var n; -return e.name === "startKnob" ? (n = this.calcRangeRatio(this.beginValue), this.doChange({ -value: n, -startChanged: !0 -})) : e.name === "endKnob" && (n = this.calcRangeRatio(this.endValue), this.doChange({ -value: n, -startChanged: !1 -})), !0; -}, -rangeMinChanged: function() { -this.refreshRangeSlider(); -}, -rangeMaxChanged: function() { -this.refreshRangeSlider(); -}, -rangeStartChanged: function() { -this.refreshRangeSlider(); -}, -rangeEndChanged: function() { -this.refreshRangeSlider(); -}, -setStartLabel: function(e) { -this.$.startKnob.waterfallDown("onSetLabel", e); -}, -setEndLabel: function(e) { -this.$.endKnob.waterfallDown("onSetLabel", e); -} -}), enyo.kind({ -name: "onyx.RangeSliderKnobLabel", -classes: "onyx-range-slider-label", -handlers: { -onSetLabel: "setLabel" -}, -setLabel: function(e, t) { -this.setContent(t); -} -}); - -// Item.js - -enyo.kind({ -name: "onyx.Item", -classes: "onyx-item", -tapHighlight: !0, -handlers: { -onhold: "hold", -onrelease: "release" -}, -hold: function(e, t) { -this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !0, t); -}, -release: function(e, t) { -this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !1, t); -}, -statics: { -addRemoveFlyweightClass: function(e, t, n, r, i) { -var s = r.flyweight; -if (s) { -var o = i !== undefined ? i : r.index; -s.performOnRow(o, function() { -e.addRemoveClass(t, n); -}); -} -} -} -}); - -// Spinner.js - -enyo.kind({ -name: "onyx.Spinner", -classes: "onyx-spinner", -stop: function() { -this.setShowing(!1); -}, -start: function() { -this.setShowing(!0); -}, -toggle: function() { -this.setShowing(!this.getShowing()); -} -}); - -// MoreToolbar.js - -enyo.kind({ -name: "onyx.MoreToolbar", -classes: "onyx-toolbar onyx-more-toolbar", -menuClass: "", -movedClass: "", -layoutKind: "FittableColumnsLayout", -noStretch: !0, -handlers: { -onHide: "reflow" -}, -published: { -clientLayoutKind: "FittableColumnsLayout" -}, -tools: [ { -name: "client", -noStretch: !0, -fit: !0, -classes: "onyx-toolbar-inline" -}, { -name: "nard", -kind: "onyx.MenuDecorator", -showing: !1, -onActivate: "activated", -components: [ { -kind: "onyx.IconButton", -classes: "onyx-more-button" -}, { -name: "menu", -kind: "onyx.Menu", -scrolling: !1, -classes: "onyx-more-menu" -} ] -} ], -initComponents: function() { -this.menuClass && this.menuClass.length > 0 && !this.$.menu.hasClass(this.menuClass) && this.$.menu.addClass(this.menuClass), this.createChrome(this.tools), this.inherited(arguments), this.$.client.setLayoutKind(this.clientLayoutKind); -}, -clientLayoutKindChanged: function() { -this.$.client.setLayoutKind(this.clientLayoutKind); -}, -reflow: function() { -this.inherited(arguments), this.isContentOverflowing() ? (this.$.nard.show(), this.popItem() && this.reflow()) : this.tryPushItem() ? this.reflow() : this.$.menu.children.length || (this.$.nard.hide(), this.$.menu.hide()); -}, -activated: function(e, t) { -this.addRemoveClass("active", t.originator.active); -}, -popItem: function() { -var e = this.findCollapsibleItem(); -if (e) { -this.movedClass && this.movedClass.length > 0 && !e.hasClass(this.movedClass) && e.addClass(this.movedClass), this.$.menu.addChild(e, null); -var t = this.$.menu.hasNode(); -return t && e.hasNode() && e.insertNodeInParent(t), !0; -} -}, -pushItem: function() { -var e = this.$.menu.children, t = e[0]; -if (t) { -this.movedClass && this.movedClass.length > 0 && t.hasClass(this.movedClass) && t.removeClass(this.movedClass), this.$.client.addChild(t); -var n = this.$.client.hasNode(); -if (n && t.hasNode()) { -var r, i; -for (var s = 0; s < this.$.client.children.length; s++) { -var o = this.$.client.children[s]; -if (o.toolbarIndex !== undefined && o.toolbarIndex != s) { -r = o, i = s; -break; -} -} -if (r && r.hasNode()) { -t.insertNodeInParent(n, r.node); -var u = this.$.client.children.pop(); -this.$.client.children.splice(i, 0, u); -} else t.appendNodeToParent(n); -} -return !0; -} -}, -tryPushItem: function() { -if (this.pushItem()) { -if (!this.isContentOverflowing()) return !0; -this.popItem(); -} -}, -isContentOverflowing: function() { -if (this.$.client.hasNode()) { -var e = this.$.client.children, t = e[e.length - 1].hasNode(); -if (t) return this.$.client.reflow(), t.offsetLeft + t.offsetWidth > this.$.client.node.clientWidth; -} -}, -findCollapsibleItem: function() { -var e = this.$.client.children; -for (var t = e.length - 1; c = e[t]; t--) { -if (!c.unmoveable) return c; -c.toolbarIndex === undefined && (c.toolbarIndex = t); -} -} -}); - -// IntegerPicker.js - -enyo.kind({ -name: "onyx.IntegerPicker", -kind: "onyx.Picker", -published: { -value: 0, -min: 0, -max: 9 -}, -create: function() { -this.inherited(arguments), this.rangeChanged(); -}, -minChanged: function() { -this.destroyClientControls(), this.rangeChanged(), this.render(); -}, -maxChanged: function() { -this.destroyClientControls(), this.rangeChanged(), this.render(); -}, -rangeChanged: function() { -for (var e = this.min; e <= this.max; e++) this.createComponent({ -content: e, -active: e === this.value ? !0 : !1 -}); -}, -valueChanged: function(e) { -var t = this.getClientControls(), n = t.length; -this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; -for (var r = 0; r < n; r++) if (this.value === parseInt(t[r].content)) { -this.setSelected(t[r]); -break; -} -}, -selectedChanged: function(e) { -e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ -selected: this.selected, -content: this.selected.content -})), this.value = parseInt(this.selected.content); -} -}); - -// ContextualPopup.js - -enyo.kind({ -name: "onyx.ContextualPopup", -kind: "enyo.Popup", -modal: !0, -autoDismiss: !0, -floating: !1, -classes: "onyx-contextual-popup enyo-unselectable", -published: { -maxHeight: 100, -scrolling: !0, -title: undefined, -actionButtons: [] -}, -vertFlushMargin: 60, -horizFlushMargin: 50, -widePopup: 200, -longPopup: 200, -horizBuffer: 16, -events: { -onTap: "" -}, -handlers: { -onActivate: "itemActivated", -onRequestShowMenu: "requestShow", -onRequestHideMenu: "requestHide" -}, -components: [ { -name: "title", -classes: "onyx-contextual-popup-title" -}, { -classes: "onyx-contextual-popup-scroller", -components: [ { -name: "client", -kind: "enyo.Scroller", -vertical: "auto", -classes: "enyo-unselectable", -thumb: !1, -strategyKind: "TouchScrollStrategy" -} ] -}, { -name: "actionButtons", -classes: "onyx-contextual-popup-action-buttons" -} ], -scrollerName: "client", -create: function() { -this.inherited(arguments), this.maxHeightChanged(), this.titleChanged(), this.actionButtonsChanged(); -}, -getScroller: function() { -return this.$[this.scrollerName]; -}, -titleChanged: function() { -this.$.title.setContent(this.title); -}, -actionButtonsChanged: function() { -for (var e = 0; e < this.actionButtons.length; e++) this.$.actionButtons.createComponent({ -kind: "onyx.Button", -content: this.actionButtons[e].content, -classes: this.actionButtons[e].classes + " onyx-contextual-popup-action-button", -name: this.actionButtons[e].name ? this.actionButtons[e].name : "ActionButton" + e, -index: e, -tap: enyo.bind(this, this.tapHandler) -}); -}, -tapHandler: function(e, t) { -return t.actionButton = !0, t.popup = this, this.bubble("ontap", t), !0; -}, -maxHeightChanged: function() { -this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); -}, -itemActivated: function(e, t) { -return t.originator.setActive(!1), !0; -}, -showingChanged: function() { -this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(); -}, -requestShow: function(e, t) { -var n = t.activator.hasNode(); -return n && (this.activatorOffset = this.getPageOffset(n)), this.show(), !0; -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -getPageOffset: function(e) { -var t = this.getBoundingRect(e), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; -return { -top: t.top + n, -left: t.left + r, -height: i, -width: s -}; -}, -adjustPosition: function() { -if (this.showing && this.hasNode()) { -this.resetPositioning(); -var e = this.getViewWidth(), t = this.getViewHeight(), n = this.vertFlushMargin, r = t - this.vertFlushMargin, i = this.horizFlushMargin, s = e - this.horizFlushMargin; -if (this.activatorOffset.top + this.activatorOffset.height < n || this.activatorOffset.top > r) { -if (this.applyVerticalFlushPositioning(i, s)) return; -if (this.applyHorizontalFlushPositioning(i, s)) return; -if (this.applyVerticalPositioning()) return; -} else if (this.activatorOffset.left + this.activatorOffset.width < i || this.activatorOffset.left > s) if (this.applyHorizontalPositioning()) return; -var o = this.getBoundingRect(this.node); -if (o.width > this.widePopup) { -if (this.applyVerticalPositioning()) return; -} else if (o.height > this.longPopup && this.applyHorizontalPositioning()) return; -if (this.applyVerticalPositioning()) return; -if (this.applyHorizontalPositioning()) return; -} -}, -initVerticalPositioning: function() { -this.resetPositioning(), this.addClass("vertical"); -var e = this.getBoundingRect(this.node), t = this.getViewHeight(); -return this.floating ? this.activatorOffset.top < t / 2 ? (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height, -bottom: "auto" -}), this.addClass("below")) : (this.applyPosition({ -top: this.activatorOffset.top - e.height, -bottom: "auto" -}), this.addClass("above")) : e.top + e.height > t && t - e.bottom < e.top - e.height ? this.addClass("above") : this.addClass("below"), e = this.getBoundingRect(this.node), e.top + e.height > t || e.top < 0 ? !1 : !0; -}, -applyVerticalPositioning: function() { -if (!this.initVerticalPositioning()) return !1; -var e = this.getBoundingRect(this.node), t = this.getViewWidth(); -if (this.floating) { -var n = this.activatorOffset.left + this.activatorOffset.width / 2 - e.width / 2; -n + e.width > t ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width - e.width -}), this.addClass("left")) : n < 0 ? (this.applyPosition({ -left: this.activatorOffset.left -}), this.addClass("right")) : this.applyPosition({ -left: n -}); -} else { -var r = this.activatorOffset.left + this.activatorOffset.width / 2 - e.left - e.width / 2; -e.right + r > t ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width - e.right -}), this.addRemoveClass("left", !0)) : e.left + r < 0 ? this.addRemoveClass("right", !0) : this.applyPosition({ -left: r -}); -} -return !0; -}, -applyVerticalFlushPositioning: function(e, t) { -if (!this.initVerticalPositioning()) return !1; -var n = this.getBoundingRect(this.node), r = this.getViewWidth(); -return this.activatorOffset.left + this.activatorOffset.width / 2 < e ? (this.activatorOffset.left + this.activatorOffset.width / 2 < this.horizBuffer ? this.applyPosition({ -left: this.horizBuffer + (this.floating ? 0 : -n.left) -}) : this.applyPosition({ -left: this.activatorOffset.width / 2 + (this.floating ? this.activatorOffset.left : 0) -}), this.addClass("right"), this.addClass("corner"), !0) : this.activatorOffset.left + this.activatorOffset.width / 2 > t ? (this.activatorOffset.left + this.activatorOffset.width / 2 > r - this.horizBuffer ? this.applyPosition({ -left: r - this.horizBuffer - n.right -}) : this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width / 2 - n.right -}), this.addClass("left"), this.addClass("corner"), !0) : !1; -}, -initHorizontalPositioning: function() { -this.resetPositioning(); -var e = this.getBoundingRect(this.node), t = this.getViewWidth(); -return this.floating ? this.activatorOffset.left + this.activatorOffset.width < t / 2 ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width -}), this.addRemoveClass("left", !0)) : (this.applyPosition({ -left: this.activatorOffset.left - e.width -}), this.addRemoveClass("right", !0)) : this.activatorOffset.left - e.width > 0 ? (this.applyPosition({ -left: this.activatorOffset.left - e.left - e.width -}), this.addRemoveClass("right", !0)) : (this.applyPosition({ -left: this.activatorOffset.width -}), this.addRemoveClass("left", !0)), this.addRemoveClass("horizontal", !0), e = this.getBoundingRect(this.node), e.left < 0 || e.left + e.width > t ? !1 : !0; -}, -applyHorizontalPositioning: function() { -if (!this.initHorizontalPositioning()) return !1; -var e = this.getBoundingRect(this.node), t = this.getViewHeight(), n = this.activatorOffset.top + this.activatorOffset.height / 2; -return this.floating ? n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 - e.height / 2, -bottom: "auto" -}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ -top: this.activatorOffset.top - this.activatorOffset.height, -bottom: "auto" -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: this.activatorOffset.top - e.height + this.activatorOffset.height * 2, -bottom: "auto" -}), this.addRemoveClass("low", !0)) : n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ -top: (this.activatorOffset.height - e.height) / 2 -}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ -top: -this.activatorOffset.height -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: e.top - e.height - this.activatorOffset.top + this.activatorOffset.height -}), this.addRemoveClass("low", !0)), !0; -}, -applyHorizontalFlushPositioning: function(e, t) { -if (!this.initHorizontalPositioning()) return !1; -var n = this.getBoundingRect(this.node), r = this.getViewWidth(); -return this.floating ? this.activatorOffset.top < innerHeight / 2 ? (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 - n.height -}), this.addRemoveClass("low", !0)) : n.top + n.height > innerHeight && innerHeight - n.bottom < n.top - n.height ? (this.applyPosition({ -top: n.top - n.height - this.activatorOffset.top - this.activatorOffset.height / 2 -}), this.addRemoveClass("low", !0)) : (this.applyPosition({ -top: this.activatorOffset.height / 2 -}), this.addRemoveClass("high", !0)), this.activatorOffset.left + this.activatorOffset.width < e ? (this.addClass("left"), this.addClass("corner"), !0) : this.activatorOffset.left > t ? (this.addClass("right"), this.addClass("corner"), !0) : !1; -}, -getBoundingRect: function(e) { -var t = e.getBoundingClientRect(); -return !t.width || !t.height ? { -left: t.left, -right: t.right, -top: t.top, -bottom: t.bottom, -width: t.right - t.left, -height: t.bottom - t.top -} : t; -}, -getViewHeight: function() { -return window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight; -}, -getViewWidth: function() { -return window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; -}, -resetPositioning: function() { -this.removeClass("right"), this.removeClass("left"), this.removeClass("high"), this.removeClass("low"), this.removeClass("corner"), this.removeClass("below"), this.removeClass("above"), this.removeClass("vertical"), this.removeClass("horizontal"), this.applyPosition({ -left: "auto" -}), this.applyPosition({ -top: "auto" -}); -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -}, -requestHide: function() { -this.setShowing(!1); -} -}); - -// App.js - -enyo.kind({ -name: "App", -kind: "FittableRows", -fit: !0, -components: [ { -kind: "onyx.Toolbar", -content: "Hello World" -}, { -kind: "enyo.Scroller", -fit: !0, -components: [ { -name: "main", -classes: "nice-padding", -allowHtml: !0 -} ] -}, { -kind: "onyx.Toolbar", -components: [ { -kind: "onyx.Button", -content: "Tap me", -ontap: "helloWorldTap" -} ] -} ], -helloWorldTap: function(e, t) { -this.$.main.addContent("The button was tapped.
    "); -} -}); diff --git a/build/enyo.css b/build/enyo.css deleted file mode 100644 index 6d05291..0000000 --- a/build/enyo.css +++ /dev/null @@ -1,181 +0,0 @@ - -/* ../source/dom/dom.css */ - -/* things we always want */ -body { - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; -} - -/* allow hw-accelerated scrolling on platforms that support it */ -body.webkitOverflowScrolling { - -webkit-overflow-scrolling: touch; -} - -/* for apps */ -.enyo-document-fit { - margin: 0; - height: 100%; - /* note: giving html overflow: auto is odd and was only ever done to avoid duplication - however, android 4.04 sometimes does not hide nodes when their display is set to none - if document is overflow auto. - */ - position: relative; -} - -.enyo-body-fit { - margin: 0; - height: 100%; - /* helps prevent ios page scroll */ - overflow: auto; - position: relative; -} - -.enyo-no-touch-action { - -ms-touch-action: none; -} - -/* reset */ - -button { - font-size: inherit; - font-family: inherit; -} -button::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* user selection */ - -.enyo-unselectable { - cursor: default; - -ms-user-select: none; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; -} - -.enyo-unselectable::selection, .enyo-unselectable ::selection { - color: transparent; -} - -.enyo-selectable { - cursor: auto; - -ms-user-select: element; - -webkit-user-select: text; - -moz-user-select: text; - user-select: text; -} - -.enyo-selectable::selection, .enyo-selectable ::selection { - background: #3297FD; - color: #FFF; -} - -/* layout */ - -body .enyo-fit { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.enyo-clip { - overflow: hidden; -} - -.enyo-border-box { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* compositing */ - -.enyo-composite { - -webkit-transform: translateZ(0); - -moz-transform: translateZ(0); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - transform: translateZ(0); -} - - -/* ../source/touch/Thumb.css */ - -.enyo-thumb { - position: absolute; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; - background: #333; - border: 1px solid #666; - opacity: 0.75; - z-index: 1; -} - -.enyo-vthumb { - top: 0; - right: 2px; - width: 4px; -} - -.enyo-hthumb { - left: 0; - bottom: 2px; - height: 4px; -} - - -/* ../source/touch/Scroller.css */ - -.enyo-scroller { - position: relative; -} - -.enyo-fit.enyo-scroller { - position: absolute; -} - -.enyo-touch-scroller { - overflow: hidden; -} - -.enyo-touch-strategy-container { - overflow: hidden; -} - -.enyo-scrollee-fit { - height: 100%; -} - -/* ../source/ui/ui.css */ - -.enyo-inline, .enyo-tool-decorator { - display: inline-block; -} - -.enyo-children-inline > *, .enyo-tool-decorator > * { - display: inline-block; -} - -.enyo-children-middle > *, .enyo-tool-decorator > * { - vertical-align: middle; -} - -.enyo-positioned { - position: relative; -} - -.enyo-fill { - position: relative; - width: 100%; - height: 100%; -} - -.enyo-popup { - position: absolute; - z-index: 10; -} diff --git a/build/enyo.js b/build/enyo.js deleted file mode 100644 index 909a6ad..0000000 --- a/build/enyo.js +++ /dev/null @@ -1,4308 +0,0 @@ - -// enyo.js - -(function() { -var e = "enyo.js"; -enyo = window.enyo || {}, enyo.locateScript = function(e) { -var t = document.getElementsByTagName("script"); -for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { -i = r.getAttribute("src") || ""; -if (i.slice(-s) == e) return r.located = !0, { -path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), -node: r -}; -} -}, enyo.args = enyo.args || {}; -var t = enyo.locateScript(e); -if (t) { -enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); -for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; -} -})(); - -// ../../loader.js - -(function() { -enyo = window.enyo || {}, enyo.pathResolverFactory = function() { -this.paths = {}; -}, enyo.pathResolverFactory.prototype = { -addPath: function(e, t) { -return this.paths[e] = t; -}, -addPaths: function(e) { -if (e) for (var t in e) this.addPath(t, e[t]); -}, -includeTrailingSlash: function(e) { -return e && e.slice(-1) !== "/" ? e + "/" : e; -}, -rewritePattern: /\$([^\/\\]*)(\/)?/g, -rewrite: function(e) { -var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { -return t = !0, n(r[i]) || ""; -}, s = e; -do t = !1, s = s.replace(this.rewritePattern, i); while (t); -return s; -} -}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { -this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; -}, enyo.loaderFactory.prototype = { -verbose: !1, -loadScript: function(e) { -this.machine.script(e); -}, -loadSheet: function(e) { -this.machine.sheet(e); -}, -loadPackage: function(e) { -this.machine.script(e); -}, -report: function() {}, -load: function() { -this.more({ -index: 0, -depends: arguments || [] -}); -}, -more: function(e) { -if (e && this.continueBlock(e)) return; -var t = this.stack.pop(); -t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); -}, -finish: function() { -this.packageFolder = "", this.verbose && console.log("-------------- fini"); -for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); -}, -continueBlock: function(e) { -while (e.index < e.depends.length) { -var t = e.depends[e.index++]; -if (t) if (typeof t == "string") { -if (this.require(t, e)) return !0; -} else this.pathResolver.addPaths(t); -} -}, -require: function(e, t) { -var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); -n = r + n; -if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { -if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; -this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); -} -}, -getPathPrefix: function(e) { -var t = e.slice(0, 1); -return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; -}, -requireStylesheet: function(e) { -this.sheets.push(e), this.loadSheet(e); -}, -requireScript: function(e, t) { -this.modules.push({ -packageName: this.packageName, -rawPath: e, -path: t -}), this.loadScript(t); -}, -decodePackagePath: function(e) { -var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; -if (s.length) { -var a = s.pop() || s.pop() || ""; -a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; -for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { -s.splice(o, 1); -break; -} -n = s.join("/"); -for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { -s = s.slice(o + 1); -break; -} -for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); -t = s.join("-"); -} -return { -alias: t, -target: n, -folder: r, -manifest: i -}; -}, -aliasPackage: function(e) { -var t = this.decodePackagePath(e); -this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ -name: t.alias, -folder: t.folder -})), this.packageFolder = t.folder; -}, -requirePackage: function(e, t) { -t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); -} -}; -})(); - -// boot.js - -enyo.execUnsafeLocalFunction = function(e) { -typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); -}, enyo.machine = { -sheet: function(e) { -var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; -r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); -var i; -enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { -document.write(''); -}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { -less.refresh(!0); -})); -}, -script: function(e, t, n) { -if (!enyo.runtimeLoading) document.write(' - - - - - - - diff --git a/deploy.md b/deploy.md deleted file mode 100644 index 009c12c..0000000 --- a/deploy.md +++ /dev/null @@ -1,52 +0,0 @@ -# Minification and Deployment -## Understanding and Using Minification - -Enyo comes with a minification tool based on UglifyJS, run by Node.js. - -This tool can be used to compress the framework, other libraries, and applications, and will keep load order intact as well as correct url paths in css. - -### Why compress? - -Compressing enyo apps greatly reduces load times of applications, as well as reducing overall code size. - -This way, you can be very verbose in the documentation of your source code, without that impacting the performance of your application in production. - -### What is compressed - -For enyo, the libraries, and your code: **external assets such as images will not be copied or moved**. - -Instead, the CSS url paths are fixed up to reference the new path from the build location. - -### How to compress - -To compress your application, you must run the Node.js script named `deploy.js` that comes with Enyo, as `enyo/tools/deploy.js`. - - $ node enyo/tools/deploy.js -h - -This script will run the minification tool located in `enyo/tools/minifier/minify.js`, and make a build of enyo, then a build of your app. - -Any libraries referenced in your `package.js` manifest will be built into your app's built code. - -**NOTE:** `deploy.js` expects to find a `package.js` in the root-folder of your application. It only references your app's `package.js` to keep paths correct. Do not modify this. - -### What comes out? - -After running the `deploy.js` script, a new folder `build` (you change this using the `-b` flag of the `deploy.js` script) will be located next to your `source` directory. - -In it will be 4 files: -- enyo.css -- enyo.js -- app.css -- app.js - -These files will be loaded in the given order by `index.html`. - -The output of the `deploy` scripts will minify your appliaction, and copy the necessary files into `deploy//`. - -If the libraries have a compatible `deploy.sh` or `deploy.bat` script, they will be executed, and a minimal copy will be placed in the deployment's lib folder. - -If no `deploy.(sh|bat)` script is found for the library, all of the library is copied into the lib folder to provide maximum safety. - -If you are adding a library, please add a `deploy.sh` file and `deploy.bat` file similar to the ones in `lib/onyx`. - -If no images or files are needed from the library, just include blank (and executable) copies of the deploy scripts. diff --git a/deploy/bootplate/assets/favicon.ico b/deploy/bootplate/assets/favicon.ico deleted file mode 100644 index 52c86347fe3e10042c05374362757fa260307d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmb`FKMnyw7{#BEC=@o4NK}++2k<9R=-ogfBntOXlHdvyYK=~#aR8MgC>3JNvw6v6 zt=*BB&9}4j&HUcH{bqoSeS!e?UBfsBlmXOj*p$tLdE23F=SqbzI8JMq)4}u`6~jJl zZFFAje9-(^L+ot9~P>KuLiljZ#* * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - /* float when not stretched */ - float: left; - clear: both; -} - -/* non-floating when stretched */ -.enyo-fittable-rows-layout.enyo-stretch > * { - float: none; - clear: none; -} - -/* setting to enforce margin collapsing */ -/* NOTE: rows cannot have margin left/right */ -.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { - float: left; - clear: both; - width: 100%; - /* note: harsh resets */ - margin-left: 0 !important; - margin-right: 0 !important; -} - -.enyo-fittable-columns-layout { - position: relative; - text-align: left; - white-space: nowrap; -} - -.enyo-fittable-columns-layout.enyo-center { - text-align: center; -} - -.enyo-fittable-columns-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - vertical-align: top; - display: inline-block; - white-space: normal; -} - -.enyo-fittable-columns-layout.enyo-tool-decorator > * { - vertical-align: middle; -} - -/* repair clobbered white-space setting for pre, code */ -.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { - white-space: pre; -} - -.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { - white-space: nowrap; -} - -/* NOTE: columns cannot have margin top/bottom */ -.enyo-fittable-columns-layout.enyo-stretch > * { - height: 100%; - /* note: harsh resets */ - margin-top: 0 !important; - margin-bottom: 0 !important; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/List.css */ - -.enyo-list { - position: relative; -} - -.enyo-list-port { - overflow: hidden; - position: relative; - height: 1000000px; -} - -.enyo-list-page, .enyo-list-holdingarea { - position: absolute; - left: 0; - right: 0; -} - -.enyo-list-holdingarea { - top: -10000px; -} - -.enyo-pinned-list-placeholder { - border: 1px solid red; - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-pinned-list-placeholder button { - width: 100px; height: 100%; - position: absolute; - top: 0; right: 0; -} - -.enyo-list-reorder-container { - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-animatedTopAndLeft { - -webkit-transition: top 0.1s linear, left 0.1s linear; - -moz-transition: top 0.1s linear, left 0.1s linear; - -o-transition: top 0.1s linear, left 0.1s linear; - transition: top 0.1s linear, left 0.1s linear; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/list/source/PulldownList.css */ - -.enyo-list-pulldown { - position: absolute; - bottom: 100%; - left: 0; - right: 0; -} - -.enyo-puller { - position: relative; - height: 50px; - font-size: 22px; - color: #444; - padding: 20px 0 0px 34px; -} - -.enyo-puller-text { - position: absolute; - left: 80px; - top: 22px; -} - -.enyo-puller-arrow { - position: relative; - background: #444; - width: 7px; - height: 28px; - transition: transform 0.3s; - -webkit-transition: -webkit-transform 0.3s; - -moz-transition: -moz-transform 0.3s; - -o-transition: -o-transform 0.3s; - -ms-transition: -ms-transform 0.3s; -} - -.enyo-puller-arrow:after { - content: " "; - height: 0; - width: 0; - position: absolute; - border: 10px solid transparent; - border-bottom-color: #444; - bottom: 100%; - left: 50%; - margin-left: -10px; -} - -.enyo-puller-arrow-up { - transform: rotate(0deg); - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -ms-transform: rotate(0deg); -} - -.enyo-puller-arrow-down { - transform: rotate(180deg); - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -o-transform: rotate(180deg); - -ms-transform: rotate(180deg); -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/arrangers/Arranger.css */ - -.enyo-arranger { - position: relative; - overflow: hidden; -} - -.enyo-arranger.enyo-fit { - position: absolute; -} - -.enyo-arranger > * { - position: absolute; - left: 0; - top: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.enyo-arranger-fit > * { - /* override any width/height set on panels */ - width: 100% !important; - height: 100% !important; - min-width: 0 !important; - min-height: 0 !important; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/panels/source/Panels.css */ - -.enyo-panels { -} - -.enyo-panels-fit-narrow { -} - -@media all and (max-width: 800px) { - .enyo-panels-fit-narrow > * { - min-width: 100%; - max-width: 100%; - } -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/tree/source/Node.css */ - -.enyo-node { - cursor: default; - padding: 4px; -} - -.enyo-node img { - vertical-align: middle; - padding-right: 6px; -} - -.enyo-node-box { - overflow: hidden; -} - -.enyo-node-client { - position: relative; -} - -.enyo-animate .enyo-node-box, .enyo-animate .enyo-node-client { - -ms-transition-property: height, top; - -ms-transition-duration: 0.2s, 0.2s; - -moz-transition-property: height, top; - -moz-transition-duration: 0.2s, 0.2s; - -o-transition-property: height, top; - -o-transition-duration: 0.2s, 0.2s; - -webkit-transition-property: height, top; - -webkit-transition-duration: 0.2s, 0.2s; - transition-property: height, top; - transition-duration: 0.2s, 0.2s; -} - - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/imageview/source/ImageViewPin.css */ - - -.pinDebug { - background:yellow; - border:1px solid yellow; -} - -/* /home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/css/onyx.less */ - -/* Onyx default parameters defined here */ -/* Fonts */ -/* ---------------------------------------*/ -/* Text Colors */ -/* ---------------------------------------*/ -/* Background Colors */ -/* ---------------------------------------*/ -/* Border Radius */ -/* ---------------------------------------*/ -/* Padding */ -/* ---------------------------------------*/ -/* Icon Sizes */ -/* ---------------------------------------*/ -/* Disabled Opacity */ -/* ---------------------------------------*/ -/* Gradient Overlays */ -/* ---------------------------------------*/ -/* Images */ -/* ---------------------------------------*/ -/* Onyx rules defined here */ -/* onyx-classes.less - combined CSS (less) files for all released Onyx controls - into single onyx.less file to avoid IE bug that allows - a maximum of 31 style sheets to be loaded before silently failing */ -.onyx { - color: #333333; - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; - font-size: 20px; - cursor: default; - background-color: #eaeaea; - /* remove automatic tap highlight color */ - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -/* prevent IE from inheriting line-height for these elements */ -.onyx button, -.onyx label, -.onyx input { - line-height: normal; -} -.onyx-selected { - background-color: #c4e3fe; -} -/* LESS pre-calculations */ -/* Individual Widget CSS */ -/* Icon.css */ -.onyx-icon, -.onyx-icon-toggle { - width: 32px; - height: 32px; - background-repeat: no-repeat; - display: inline-block; - vertical-align: middle; -} -.onyx-icon.onyx-icon-button.active, -.onyx-icon.onyx-icon-button.pressed, -.onyx-icon.onyx-icon-button:active:hover, -.onyx-icon-toggle.active { - background-position: 0 -32px; -} -.onyx-icon.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-icon.disabled:active:hover { - background-position: 0 0px; -} -/* Button.css */ -.onyx-button { - outline: 0; - color: #292929; - font-size: 16px; - text-align: center; - white-space: nowrap; - margin: 0; - padding: 6px 18px; - overflow: hidden; - border-radius: 3px; - /* for IE8 */ - - border: 1px solid #707070; - border: 1px solid rgba(15, 15, 15, 0.2); - /* - The border and the gradient interact in a strange way that - causes the bottom-border (top if the gradient is aligned top) - to be lighter than other borders. - We can fix it by using the darker bottom border below, but - then there are a few rogue pixels that end up very dark. - */ - - /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ - - box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); - background: #e1e1e1 url(../lib/onyx/images/gradient.png) repeat-x bottom; - background-size: contain; - /**/ - - text-overflow: ellipsis; - /* the following cause arcane problems on IE */ - - /* - min-width: 14px; - min-height: 20px; - */ - -} -/* - IE8 can't handle these selectors in tandem: - .onyx-button.active, .onyx-button:active:not([disabled]) { - - the effect is as if .onyx-button.active doesn't exist -*/ -.onyx-button.active, -.onyx-button.pressed { - background-image: url(../lib/onyx/images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button:active:hover:not([disabled]) { - background-image: url(../lib/onyx/images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button[disabled] { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-button > img { - padding: 0px 3px; -} -/* Remove the focused inner-border style in Firefox (Windows) */ -.onyx-button::-moz-focus-inner { - border: 0; -} -/* Checkbox.css */ -.onyx-checkbox { - cursor: pointer; - height: 32px; - width: 32px; - background: url(../lib/onyx/images/checkbox.png) no-repeat; - /* reset for ? */ - - margin: 0px; - /* these entries cause toggle-button and checkbox to line up properly*/ - - display: inline-block; - vertical-align: middle; -} -.onyx-checkbox[checked] { - background-position: 0px -32px; -} -.onyx-checkbox[disabled] { - opacity: 0.4; -} -/* Grabber.css */ -.onyx-grabber { - background: url(../lib/onyx/images/grabbutton.png) no-repeat center; - width: 23px; - height: 27px; -} -/* Popup.css */ -.onyx-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; -} -.onyx-popup-decorator { - position: relative; -} -/* Groupbox.css */ -.onyx-groupbox > * { - display: block; - /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ - - border-color: #aaaaaa; - border-style: solid; - border-width: 0 1px 1px 1px; - /*padding: 10px;*/ - - /* reset styles that make 'item' look bad if they happen to be there */ - - border-radius: 0; - margin: 0; - font-size: 16px; -} -.onyx-groupbox > *:first-child { - border-top-color: #aaaaaa; - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > *:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > *:first-child:last-child { - border-radius: 4px; -} -.onyx-groupbox-header { - padding: 2px 10px; - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; - /**/ - - background-color: #4c4c4c; - border: none; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 10px; -} -.onyx-groupbox .onyx-input-decorator { - display: block; -} -.onyx-groupbox > .onyx-input-decorator { - border-color: #aaaaaa; - border-width: 0 1px 1px 1px; - border-radius: 0; -} -.onyx-groupbox > .onyx-input-decorator:first-child { - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > .onyx-input-decorator:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > .onyx-input-decorator:first-child:last-child { - border-radius: 4px; -} -/* Input.css */ -.onyx-input-decorator { - padding: 6px 8px 10px 8px; - border-radius: 3px; - border: 1px solid; - border-color: rgba(0, 0, 0, 0.1); - margin: 0; -} -.onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - border-color: rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-input-decorator.onyx-disabled { - /* FIXME: needed to color a disabled input placeholder. */ - - /*-webkit-text-fill-color: #888;*/ - - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-input-decorator > input { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > input { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > input { - cursor: default; -} -/* Menu.css */ -.onyx-menu, -.onyx.onyx-menu { - min-width: 160px; - top: 100%; - left: 0; - margin-top: 2px; - padding: 3px 0; - border-radius: 3px; -} -.onyx-menu.onyx-menu-up { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 2px; -} -.onyx-toolbar .onyx-menu { - margin-top: 11px; - border-radius: 0 0 3px 3px; -} -.onyx-toolbar .onyx-menu.onyx-menu-up { - margin-top: 0; - margin-bottom: 10px; - border-radius: 3px 3px 0 0; -} -.onyx-menu-item { - display: block; - padding: 10px; -} -.onyx-menu-item:hover { - background: #284152; -} -.onyx-menu-divider, -.onyx-menu-divider:hover { - margin: 6px 0; - padding: 0; - border-bottom: 1px solid #aaa; -} -.onyx-menu-label { - cursor: default; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-menu-label:hover { - background: none; -} -/* customize a toolbar to support menus */ -.onyx-menu-toolbar, -.onyx-toolbar.onyx-menu-toolbar { - position: relative; - z-index: 10; - overflow: visible; -} -/* Picker.css */ -.onyx-picker-decorator .onyx-button { - padding: 10px 18px; -} -.onyx-picker { - top: 0; - margin-top: -3px; - min-width: 0; - width: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; - color: black; - background: #e1e1e1; -} -.onyx-picker.onyx-menu-up { - top: auto; - bottom: 0; - margin-top: 3px; - margin-bottom: -3px; -} -.onyx-picker .onyx-menu-item { - text-align: center; -} -.onyx-picker .onyx-menu-item:hover { - background-color: transparent; -} -.onyx-picker .onyx-menu-item.selected, -.onyx-picker .onyx-menu-item.active, -.onyx-picker .onyx-menu-item:active:hover { - border-top: 1px solid rgba(0, 0, 0, 0.1); - background-color: #cde7fe; - box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); -} -.onyx-picker .onyx-menu-item { - border-top: 1px solid rgba(255, 255, 255, 0.5); - border-bottom: 1px solid rgba(0, 0, 0, 0.2); -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, -.onyx-flyweight-picker :first-child > .onyx-menu-item { - border-top: none; -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, -.onyx-flyweight-picker :last-child > .onyx-menu-item { - border-bottom: none; -} -/* TextArea.css */ -.onyx-input-decorator > textarea { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* Remove scrollbars and resize handle */ - - resize: none; - overflow: auto; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > textarea { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > textarea { - cursor: default; -} -.onyx-textarea { - /* need >=50px for scrollbar to be usable on mac */ - - min-height: 50px; -} -/* RichText.css */ -.onyx-input-decorator > .onyx-richtext { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - min-height: 20px; - min-width: 100px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > .onyx-richtext { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > .onyx-richtext { - cursor: default; -} -/* RadioButton.css */ -.onyx-radiobutton { - padding: 8px 12px; - margin: 0; - outline: 0; - font-size: 16px; - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); - text-align: center; - /**/ - - background: #e7e7e7 url(../lib/onyx/images/gradient.png) repeat-x bottom; - /* IE8 */ - - border: 1px solid #333333; - border: 1px solid rgba(15, 15, 15, 0.2); - /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ - - border-right-color: rgba(0, 0, 0, 0); - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); -} -.onyx-radiobutton:first-child { - border-radius: 3px 0 0 3px; -} -.onyx-radiobutton:last-child { - border-radius: 0px 3px 3px 0px; - /* IE8 */ - - border-right: 1px solid #333333; - border-right: 1px solid rgba(15, 15, 15, 0.2); -} -.onyx-radiobutton.active { - color: #ffffff; - background: #0091f2 url(../lib/onyx/images/gradient-invert.png) repeat-x top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); -} -/* Scrim.css */ -.onyx-scrim { - z-index: 1; - /* - note: by using pointer-events we allow tapping on scrim - while it is fading out; however, this requires any showing classes - to set pointer events to auto or scrim will not function as expected. - */ - - pointer-events: none; -} -.onyx-scrim.onyx-scrim-translucent { - pointer-events: auto; - background-color: #000000; - opacity: 0.65; - filter: alpha(opacity=65); -} -.onyx-scrim.onyx-scrim-transparent { - pointer-events: auto; - background: transparent; -} -/* TabButton.css */ -.onyx-radiobutton.onyx-tabbutton { - padding: 8px 34px; - font-size: 20px; - border-radius: 0px; -} -/* ToggleButton.css */ -.onyx-toggle-button { - display: inline-block; - height: 32px; - line-height: 32px; - min-width: 64px; - vertical-align: middle; - text-align: center; - /* */ - - border-radius: 3px; - box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); - background: #8bba3d url(../lib/onyx/images/gradient-invert.png) repeat-x bottom; - background-size: auto 100%; - /* label */ - - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; -} -.onyx-toggle-button.off { - background-color: #b1b1b1 !important; -} -.onyx-toggle-button-knob { - display: inline-block; - width: 30px; - height: 30px; - margin: 1px; - border-radius: 3px; - background: #f6f6f6 url(../lib/onyx/images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-toggle-button .onyx-toggle-button-knob { - box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: right; -} -.onyx-toggle-button.off .onyx-toggle-button-knob { - box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: left; -} -.onyx-toggle-button.disabled, -.onyx-icon-button.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-toggle-content { - min-width: 32px; - padding: 0 6px; -} -.onyx-toggle-content.empty { - padding: 0; -} -.onyx-toggle-content.off { - float: right; -} -.onyx-toggle-content.on { - float: left; -} -/* Toolbar.css */ -.onyx-toolbar { - /* - line-height is unreliable for centering, instead - use vertical-align: middle to align - elements along a common centerline and use - padding to fill out the space. - */ - - padding: 9px 8px 10px 8px; - border: 1px solid #3A3A3A; - background: #4c4c4c url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; - background-size: contain; - color: #ffffff; - /**/ - - white-space: nowrap; - overflow-y: visible; - font-size: 20px; -} -.onyx-toolbar-inline > *, -.enyo-fittable-columns-layout.onyx-toolbar-inline > * { - display: inline-block; - vertical-align: middle; - margin: 4px 6px 5px; - box-sizing: border-box; -} -.onyx-toolbar .onyx-icon-button { - margin: 3px 2px 1px; -} -.onyx-toolbar .onyx-button { - color: #f2f2f2; - background-color: #555656; - border-color: rgba(15, 15, 15, 0.5); - margin-top: 0; - margin-bottom: 0; - height: 36px; -} -.onyx-toolbar .onyx-input-decorator { - margin: 1px 3px; - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.1); - padding: 0px 6px 5px 6px; -} -.onyx-toolbar .onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-toolbar .onyx-input-decorator .onyx-input { - color: #e5e5e5; - font-size: 14px; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus { - color: #000000; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { - color: #dddddd; -} -/* Tooltip.css */ -.onyx-tooltip { - z-index: 20; - left: 0; - padding: 4px 6px; - margin-top: 4px; - margin-left: -6px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - color: #ffffff; - background: #216593 url(../lib/onyx/images/gradient.png) repeat-x 0 bottom; - border-radius: 3px; - white-space: nowrap; -} -/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ -.onyx-tooltip.right-arrow { - left: 30px; -} -/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ -.onyx-tooltip::before { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - left: 16px; -} -.onyx-tooltip::after { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - margin-left: -12px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ -.onyx-tooltip.below { - top: 100%; -} -.onyx-tooltip.below.right-arrow::after { - border-bottom: 6px solid #1D587F; - top: -6px; -} -.onyx-tooltip.below.left-arrow::before { - border-bottom: 6px solid #1D587F; - top: -6px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ -.onyx-tooltip.above { - top: -100%; -} -.onyx-tooltip.above.right-arrow::after { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -.onyx-tooltip.above.left-arrow::before { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -/* ProgressBar.css */ -.onyx-progress-bar { - margin: 8px; - height: 8px; - border: 1px solid rgba(15, 15, 15, 0.2); - border-radius: 3px; - background: #b8b8b8 url(../lib/onyx/images/gradient-invert.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar { - height: 100%; - border-radius: 3px; - background: #58abef url(../lib/onyx/images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar.striped { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} -.onyx-progress-bar-bar.striped.animated { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -/* ProgressButton.css */ -.onyx-progress-button { - position: relative; - height: 36px; - line-height: 36px; - color: #f1f1f1; - font-size: 16px; - text-overflow: ellipsis; -} -.onyx-progress-button-bar { - height: 36px; -} -.onyx-progress-button-icon { - display: inline-block; - position: absolute; - top: 2px; - right: 0; -} -.onyx-progress-button-client { - display: inline-block; - position: absolute; - top: 0; - left: 0; - right: 36px; - margin-left: 8px; -} -.onyx-progress-button-client > * { - display: inline-block; -} -/* Slider.css */ -.onyx-slider { - position: relative; - margin: 8px 20px; -} -.onyx-slider-taparea { - position: absolute; - top: -11px; - height: 28px; - width: 100%; -} -.onyx-slider-knob { - position: relative; - height: 40px; - width: 40px; - background: url(../lib/onyx/images/slider-handle.png) left top no-repeat; - margin: -23px -20px; -} -.onyx-slider-knob.active, -.onyx-slider-knob.pressed, -.onyx-slider-knob:active:hover { - background-position: 0 -40px; -} -/* RangeSlider.css */ -.onyx-range-slider-knob { - top: -17px; -} -.onyx-range-slider-label { - position: relative; - top: -18px; - text-align: center; - white-space: nowrap; -} -/* Item.css */ -.onyx-item { - padding: 14px; -} -.onyx-highlight, -.onyx-highlight.onyx-swipeable-item-content { - background-color: #dedfdf; -} -.enyo-selected, -.enyo-selected.onyx-swipeable-item-content { - background-color: #c4e3fe; -} -.onyx-item.onyx-swipeable-item { - overflow: hidden; - padding: 0; -} -.onyx-swipeable-item-content { - background-color: #eaeaea; - box-sizing: border-box; - padding: 18px 6px; - min-height: 40px; -} -/* Spinner.css */ -.onyx-spinner { - width: 59px; - height: 58px; - display: inline-block; - background: url(../lib/onyx/images/spinner-dark.gif) no-repeat 0 0; -} -.onyx-spinner.onyx-light { - background: url(../lib/onyx/images/spinner-light.gif) no-repeat 0 0; -} -/* MoreToolbar.css */ -.onyx-more-toolbar { - overflow: visible; - position: relative; - z-index: 10; -} -.onyx-more-toolbar.active { - z-index: 11; -} -.onyx-more-menu { - left: auto; - right: 0px; - min-width: 0; -} -.onyx-more-toolbar .onyx-more-menu > * { - float: right; - clear: both; - margin: 5px; - margin-top: 5px; - margin-bottom: 5px; -} -.onyx-more-button { - background-image: url(../lib/onyx/images/more.png); - width: 32px; - height: 32px; -} -/* DatePicker.css */ -.onyx-datepicker-month { - min-width: 75px; -} -.onyx-datepicker-day { - min-width: 60px; -} -.onyx-datepicker-year { - min-width: 70px; -} -/* TimePicker.css */ -.onyx-timepicker-hour { - min-width: 60px; -} -.onyx-timepicker-minute { - min-width: 60px; -} -.onyx-timepicker-ampm { - min-width: 60px; -} -/* ButtonColors.css */ -.onyx-button.onyx-blue { - background-color: #35A8EE; - color: #F2F2F2; -} -.onyx-button.onyx-affirmative { - background-color: #91BA07; - color: #F2F2F2; -} -.onyx-button.onyx-negative { - background-color: #C51616; - color: #F2F2F2; -} -.onyx-button.onyx-dark { - background-color: #555656; - color: #F2F2F2; -} -.onyx-button.onyx-light { - background-color: #cacaca; - color: #2F2F2F; -} -/* ContextualPopup.css */ -.onyx-contextual-popup-title { - font-weight: bold; - padding: 24px 32px 0px; -} -.onyx-contextual-popup-scroller { - padding: 24px 32px; -} -.onyx-contextual-popup-action-buttons { - display: inline-block; - width: 100%; - text-align: center; -} -.onyx-contextual-popup-action-button { - margin-left: 5px; - margin-right: 5px; -} -.onyx-contextual-popup, -.onyx.onyx-contextual-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c; -} -/*setup the nub*/ -.onyx-contextual-popup::after { - content: ''; - position: absolute; - top: -10px; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; -} -/*for popups above activator*/ -.onyx-contextual-popup.vertical.above { - top: auto; - margin-top: -10px; - bottom: 100%; - margin-bottom: 10px; -} -/*for popups below activator*/ -.onyx-contextual-popup.vertical.below { - margin-top: 10px; -} -/*for popups on the left of the activator*/ -.onyx-contextual-popup.right.horizontal { - margin-left: -11px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.left.horizontal { - margin-left: 10px; -} -/*nub positioning*/ -/*horizontally centered nub*/ -.onyx-contextual-popup.vertical::after { - position: absolute; - left: 45%; - border-bottom: 10px solid #4c4c4c; - border-top: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -/*nub near horizontal left*/ -.onyx-contextual-popup.vertical.right::after { - left: 0%; - margin-left: 20px; -} -/*nub near horizontal right*/ -.onyx-contextual-popup.vertical.left::after { - left: 100%; - margin-left: -55px; -} -/*downward facing nub*/ -.onyx-contextual-popup.vertical.above::after { - top: 100%; - border-top: 10px solid #4c4c4c; - border-bottom: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right::after { - top: 0%; - margin-top: -10px; - border-bottom: 10px solid #4c4c4c; - border-left: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.left::after { - top: 0%; - margin-top: -10px; - border-right: 10px solid transparent; -} -/*nub positioning for left/right popups*/ -/*vertically centered nub for popups on left of activator*/ -.onyx-contextual-popup.right::after { - left: 100%; - top: 47%; - margin-right: 20px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on left of activator*/ -.onyx-contextual-popup.right.high::after { - top: 35px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on left of activator*/ -.onyx-contextual-popup.right.low::after { - top: 100%; - margin-top: -55px; - border-left: 10px solid #4C4C4C; -} -/*vertically centered nub for popups on right of activator*/ -.onyx-contextual-popup.left::after { - left: 0%; - margin-left: -20px; - top: 45%; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on right of activator*/ -.onyx-contextual-popup.left.high::after { - top: 35px; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on right of activator*/ -.onyx-contextual-popup.left.low::after { - top: 100%; - margin-top: -55px; - border-right: 10px solid #4C4C4C; -} -/*corners*/ -/*vertical top corners*/ -/*for popups on the left of the activator*/ -.onyx-contextual-popup.vertical.right.corner { - margin-left: 0px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.vertical.left.corner { - margin-left: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.vertical.below.right.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner::after { - top: 0%; - left: 100%; - margin-top: -10px; - margin-left: -19px; - border-right: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right.corner::after { - top: 0%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -/*vertical bottom corners*/ -.onyx-contextual-popup.left.above.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.right.above.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.vertical.left.above.corner::after { - top: 100%; - margin-left: -19px; - border-right: 10px solid #4C4C4C; - border-bottom: 10px solid transparent; - border-top: none; -} -.onyx-contextual-popup.vertical.right.above.corner::after { - top: 100%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-bottom: 10px solid transparent; - border-top: none; -} -/*horizontal bottom corners*/ -.onyx-contextual-popup.left.low.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.right.low.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.left.low.corner::after { - top: 100%; - left: 0%; - margin-top: -19px; - margin-left: -12px; - border-bottom: 10px solid #4c4c4c; - border-right: 10px solid #4c4c4c; -} -.onyx-contextual-popup.right.low.corner::after { - top: 100%; - left: 100%; - margin-top: -19px; - border-bottom: 10px solid#4c4c4c; - border-left: none; -} -/*horizontal top corners*/ -.onyx-contextual-popup.left.high.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.right.high.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.left.high.corner::after { - top: 0%; - left: 0%; - margin-top: -1px; - margin-left: -12px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -.onyx-contextual-popup.right.high.corner::after { - top: 0%; - left: 100%; - margin-top: -1px; - margin-left: -9px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -/* some default colors */ -.onyx-dark { - background-color: #555656; -} -.onyx-light { - background-color: #cacaca; -} -.onyx-green { - background-color: #91BA07; -} -.onyx-red { - background-color: #C51616; -} -.onyx-blue { - background-color: #35A8EE; -} - - -/* source/App.css */ - -/* - Put anything you reference with "url(../source)" in ../assets/ - This way, you can minify your application, and just remove the "source" folder for production -*/ -.nice-padding { - padding: 15px; -} diff --git a/deploy/bootplate/build/app.js b/deploy/bootplate/build/app.js deleted file mode 100644 index 7a17c89..0000000 --- a/deploy/bootplate/build/app.js +++ /dev/null @@ -1,4447 +0,0 @@ - -// minifier: path aliases - -enyo.path.addPaths({layout: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/layout/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/", onyx: "/home/reviewdaemon/hudson/trunk/agent/workspace/Enyo-github-build/bootplate/enyo/../lib/onyx/source/"}); - -// FittableLayout.js - -enyo.kind({ -name: "enyo.FittableLayout", -kind: "Layout", -calcFitIndex: function() { -for (var e = 0, t = this.container.children, n; n = t[e]; e++) if (n.fit && n.showing) return e; -}, -getFitControl: function() { -var e = this.container.children, t = e[this.fitIndex]; -return t && t.fit && t.showing || (this.fitIndex = this.calcFitIndex(), t = e[this.fitIndex]), t; -}, -getLastControl: function() { -var e = this.container.children, t = e.length - 1, n = e[t]; -while ((n = e[t]) && !n.showing) t--; -return n; -}, -_reflow: function(e, t, n, r) { -this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); -var i = this.getFitControl(); -if (!i) return; -var s = 0, o = 0, u = 0, a, f = this.container.hasNode(); -f && (a = enyo.dom.calcPaddingExtents(f), s = f[t] - (a[n] + a[r])); -var l = i.getBounds(); -o = l[n] - (a && a[n] || 0); -var c = this.getLastControl(); -if (c) { -var h = enyo.dom.getComputedBoxValue(c.hasNode(), "margin", r) || 0; -if (c != i) { -var p = c.getBounds(), d = l[n] + l[e], v = p[n] + p[e] + h; -u = v - d; -} else u = h; -} -var m = s - (o + u); -i.applyStyle(e, m + "px"); -}, -reflow: function() { -this.orient == "h" ? this._reflow("width", "clientWidth", "left", "right") : this._reflow("height", "clientHeight", "top", "bottom"); -} -}), enyo.kind({ -name: "enyo.FittableColumnsLayout", -kind: "FittableLayout", -orient: "h", -layoutClass: "enyo-fittable-columns-layout" -}), enyo.kind({ -name: "enyo.FittableRowsLayout", -kind: "FittableLayout", -layoutClass: "enyo-fittable-rows-layout", -orient: "v" -}); - -// FittableRows.js - -enyo.kind({ -name: "enyo.FittableRows", -layoutKind: "FittableRowsLayout", -noStretch: !1 -}); - -// FittableColumns.js - -enyo.kind({ -name: "enyo.FittableColumns", -layoutKind: "FittableColumnsLayout", -noStretch: !1 -}); - -// FlyweightRepeater.js - -enyo.kind({ -name: "enyo.FlyweightRepeater", -published: { -count: 0, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -clientClasses: "", -clientStyle: "", -rowOffset: 0 -}, -events: { -onSetupItem: "", -onRenderRow: "" -}, -bottomUp: !1, -components: [ { -kind: "Selection", -onSelect: "selectDeselect", -onDeselect: "selectDeselect" -}, { -name: "client" -} ], -create: function() { -this.inherited(arguments), this.noSelectChanged(), this.multiSelectChanged(), this.clientClassesChanged(), this.clientStyleChanged(); -}, -noSelectChanged: function() { -this.noSelect && this.$.selection.clear(); -}, -multiSelectChanged: function() { -this.$.selection.setMulti(this.multiSelect); -}, -clientClassesChanged: function() { -this.$.client.setClasses(this.clientClasses); -}, -clientStyleChanged: function() { -this.$.client.setStyle(this.clientStyle); -}, -setupItem: function(e) { -this.doSetupItem({ -index: e, -selected: this.isSelected(e) -}); -}, -generateChildHtml: function() { -var e = ""; -this.index = null; -for (var t = 0, n = 0; t < this.count; t++) n = this.rowOffset + (this.bottomUp ? this.count - t - 1 : t), this.setupItem(n), this.$.client.setAttribute("data-enyo-index", n), e += this.inherited(arguments), this.$.client.teardownRender(); -return e; -}, -previewDomEvent: function(e) { -var t = this.index = this.rowForEvent(e); -e.rowIndex = e.index = t, e.flyweight = this; -}, -decorateEvent: function(e, t, n) { -var r = t && t.index != null ? t.index : this.index; -t && r != null && (t.index = r, t.flyweight = this), this.inherited(arguments); -}, -tap: function(e, t) { -if (this.noSelect || t.index === -1) return; -this.toggleSelected ? this.$.selection.toggle(t.index) : this.$.selection.select(t.index); -}, -selectDeselect: function(e, t) { -this.renderRow(t.key); -}, -getSelection: function() { -return this.$.selection; -}, -isSelected: function(e) { -return this.getSelection().isSelected(e); -}, -renderRow: function(e) { -if (e < this.rowOffset || e >= this.count + this.rowOffset) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -t && (enyo.dom.setInnerHtml(t, this.$.client.generateChildHtml()), this.$.client.teardownChildren(), this.doRenderRow({ -rowIndex: e -})); -}, -fetchRowNode: function(e) { -if (this.hasNode()) return this.node.querySelector('[data-enyo-index="' + e + '"]'); -}, -rowForEvent: function(e) { -if (!this.hasNode()) return -1; -var t = e.target; -while (t && t !== this.node) { -var n = t.getAttribute && t.getAttribute("data-enyo-index"); -if (n !== null) return Number(n); -t = t.parentNode; -} -return -1; -}, -prepareRow: function(e) { -if (e < 0 || e >= this.count) return; -this.setupItem(e); -var t = this.fetchRowNode(e); -enyo.FlyweightRepeater.claimNode(this.$.client, t); -}, -lockRow: function() { -this.$.client.teardownChildren(); -}, -performOnRow: function(e, t, n) { -if (e < 0 || e >= this.count) return; -t && (this.prepareRow(e), enyo.call(n || null, t), this.lockRow()); -}, -statics: { -claimNode: function(e, t) { -var n; -t && (t.id !== e.id ? n = t.querySelector("#" + e.id) : n = t), e.generated = Boolean(n || !e.tag), e.node = n, e.node && e.rendered(); -for (var r = 0, i = e.children, s; s = i[r]; r++) this.claimNode(s, t); -} -} -}); - -// List.js - -enyo.kind({ -name: "enyo.List", -kind: "Scroller", -classes: "enyo-list", -published: { -count: 0, -rowsPerPage: 50, -bottomUp: !1, -noSelect: !1, -multiSelect: !1, -toggleSelected: !1, -fixedHeight: !1, -reorderable: !1, -centerReorderContainer: !0, -reorderComponents: [], -pinnedReorderComponents: [], -swipeableComponents: [], -enableSwipe: !1, -persistSwipeableItem: !1 -}, -events: { -onSetupItem: "", -onSetupReorderComponents: "", -onSetupPinnedReorderComponents: "", -onReorder: "", -onSetupSwipeItem: "", -onSwipeDrag: "", -onSwipe: "", -onSwipeComplete: "" -}, -handlers: { -onAnimateFinish: "animateFinish", -onRenderRow: "rowRendered", -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onup: "up", -onholdpulse: "holdpulse" -}, -rowHeight: 0, -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0;" -} ] -} ], -reorderHoldTimeMS: 600, -draggingRowIndex: -1, -draggingRowNode: null, -placeholderRowIndex: -1, -dragToScrollThreshold: .1, -prevScrollTop: 0, -autoScrollTimeoutMS: 20, -autoScrollTimeout: null, -autoscrollPageY: 0, -pinnedReorderMode: !1, -initialPinPosition: -1, -itemMoved: !1, -currentPageNumber: -1, -completeReorderTimeout: null, -swipeIndex: null, -swipeDirection: null, -persistentItemVisible: !1, -persistentItemOrigin: null, -swipeComplete: !1, -completeSwipeTimeout: null, -completeSwipeDelayMS: 500, -normalSwipeSpeedMS: 200, -fastSwipeSpeedMS: 100, -percentageDraggedThreshold: .2, -importProps: function(e) { -e && e.reorderable && (this.touch = !0), this.inherited(arguments); -}, -create: function() { -this.pageHeights = [], this.inherited(arguments), this.getStrategy().translateOptimized = !0, this.bottomUpChanged(), this.noSelectChanged(), this.multiSelectChanged(), this.toggleSelectedChanged(), this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count); -}, -initComponents: function() { -this.createReorderTools(), this.inherited(arguments), this.createSwipeableComponents(); -}, -createReorderTools: function() { -this.createComponent({ -name: "reorderContainer", -classes: "enyo-list-reorder-container", -ondown: "sendToStrategy", -ondrag: "sendToStrategy", -ondragstart: "sendToStrategy", -ondragfinish: "sendToStrategy", -onflick: "sendToStrategy" -}); -}, -createStrategy: function() { -this.controlParentName = "strategy", this.inherited(arguments), this.createChrome(this.listTools), this.controlParentName = "client", this.discoverControlParent(); -}, -createSwipeableComponents: function() { -for (var e = 0; e < this.swipeableComponents.length; e++) this.$.swipeableComponents.createComponent(this.swipeableComponents[e], { -owner: this.owner -}); -}, -rendered: function() { -this.inherited(arguments), this.$.generator.node = this.$.port.hasNode(), this.$.generator.generated = !0, this.reset(); -}, -resizeHandler: function() { -this.inherited(arguments), this.refresh(); -}, -bottomUpChanged: function() { -this.$.generator.bottomUp = this.bottomUp, this.$.page0.applyStyle(this.pageBound, null), this.$.page1.applyStyle(this.pageBound, null), this.pageBound = this.bottomUp ? "bottom" : "top", this.hasNode() && this.reset(); -}, -noSelectChanged: function() { -this.$.generator.setNoSelect(this.noSelect); -}, -multiSelectChanged: function() { -this.$.generator.setMultiSelect(this.multiSelect); -}, -toggleSelectedChanged: function() { -this.$.generator.setToggleSelected(this.toggleSelected); -}, -countChanged: function() { -this.hasNode() && this.updateMetrics(); -}, -sendToStrategy: function(e, t) { -this.$.strategy.dispatchEvent("on" + t.type, t, e); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.portSize = 0; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -holdpulse: function(e, t) { -if (!this.getReorderable() || this.isReordering()) return; -if (t.holdTime >= this.reorderHoldTimeMS && this.shouldStartReordering(e, t)) return t.preventDefault(), this.startReordering(t), !1; -}, -dragstart: function(e, t) { -if (this.isReordering()) return !0; -if (this.isSwipeable()) return this.swipeDragStart(e, t); -}, -drag: function(e, t) { -if (this.shouldDoReorderDrag(t)) return t.preventDefault(), this.reorderDrag(t), !0; -if (this.isSwipeable()) return t.preventDefault(), this.swipeDrag(e, t), !0; -}, -dragfinish: function(e, t) { -this.isReordering() ? this.finishReordering(e, t) : this.isSwipeable() && this.swipeDragFinish(e, t); -}, -up: function(e, t) { -this.isReordering() && this.finishReordering(e, t); -}, -generatePage: function(e, t) { -this.page = e; -var n = this.rowsPerPage * this.page; -this.$.generator.setRowOffset(n); -var r = Math.min(this.count - n, this.rowsPerPage); -this.$.generator.setCount(r); -var i = this.$.generator.generateChildHtml(); -t.setContent(i), this.getReorderable() && this.draggingRowIndex > -1 && this.hideReorderingRow(); -var s = t.getBounds().height; -!this.rowHeight && s > 0 && (this.rowHeight = Math.floor(s / r), this.updateMetrics()); -if (!this.fixedHeight) { -var o = this.getPageHeight(e); -this.pageHeights[e] = s, this.portSize += s - o; -} -}, -pageForRow: function(e) { -return Math.floor(e / this.rowsPerPage); -}, -preserveDraggingRowNode: function(e) { -this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === e && (this.$.holdingarea.hasNode().appendChild(this.draggingRowNode), this.draggingRowNode = null, this.removedInitialPage = !0); -}, -update: function(e) { -var t = !1, n = this.positionToPageInfo(e), r = n.pos + this.scrollerHeight / 2, i = Math.floor(r / Math.max(n.height, this.scrollerHeight) + .5) + n.no, s = i % 2 === 0 ? i : i - 1; -this.p0 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p0), this.generatePage(s, this.$.page0), this.positionPage(s, this.$.page0), this.p0 = s, t = !0, this.p0RowBounds = this.getPageRowHeights(this.$.page0)), s = i % 2 === 0 ? Math.max(1, i - 1) : i, this.p1 != s && this.isPageInRange(s) && (this.preserveDraggingRowNode(this.p1), this.generatePage(s, this.$.page1), this.positionPage(s, this.$.page1), this.p1 = s, t = !0, this.p1RowBounds = this.getPageRowHeights(this.$.page1)), t && (this.$.generator.setRowOffset(0), this.$.generator.setCount(this.count), this.fixedHeight || (this.adjustBottomPage(), this.adjustPortSize())); -}, -getPageRowHeights: function(e) { -var t = {}, n = e.hasNode().querySelectorAll("div[data-enyo-index]"); -for (var r = 0, i, s; r < n.length; r++) i = n[r].getAttribute("data-enyo-index"), i !== null && (s = enyo.dom.getBounds(n[r]), t[parseInt(i, 10)] = { -height: s.height, -width: s.width -}); -return t; -}, -updateRowBounds: function(e) { -this.p0RowBounds[e] ? this.updateRowBoundsAtIndex(e, this.p0RowBounds, this.$.page0) : this.p1RowBounds[e] && this.updateRowBoundsAtIndex(e, this.p1RowBounds, this.$.page1); -}, -updateRowBoundsAtIndex: function(e, t, n) { -var r = n.hasNode().querySelector('div[data-enyo-index="' + e + '"]'), i = enyo.dom.getBounds(r); -t[e].height = i.height, t[e].width = i.width; -}, -updateForPosition: function(e) { -this.update(this.calcPos(e)); -}, -calcPos: function(e) { -return this.bottomUp ? this.portSize - this.scrollerHeight - e : e; -}, -adjustBottomPage: function() { -var e = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; -this.positionPage(e.pageNo, e); -}, -adjustPortSize: function() { -this.scrollerHeight = this.getBounds().height; -var e = Math.max(this.scrollerHeight, this.portSize); -this.$.port.applyStyle("height", e + "px"); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e); -t.applyStyle(this.pageBound, n + "px"); -}, -pageToPosition: function(e) { -var t = 0, n = e; -while (n > 0) n--, t += this.getPageHeight(n); -return t; -}, -positionToPageInfo: function(e) { -var t = -1, n = this.calcPos(e), r = this.defaultPageHeight; -while (n >= 0) t++, r = this.getPageHeight(t), n -= r; -return t = Math.max(t, 0), { -no: t, -height: r, -pos: n + r, -startRow: t * this.rowsPerPage, -endRow: Math.min((t + 1) * this.rowsPerPage - 1, this.count - 1) -}; -}, -isPageInRange: function(e) { -return e == Math.max(0, Math.min(this.pageCount - 1, e)); -}, -getPageHeight: function(e) { -var t = this.pageHeights[e]; -if (!t) { -var n = this.rowsPerPage * e, r = Math.min(this.count - n, this.rowsPerPage); -t = this.defaultPageHeight * (r / this.rowsPerPage); -} -return Math.max(1, t); -}, -invalidatePages: function() { -this.p0 = this.p1 = null, this.p0RowBounds = {}, this.p1RowBounds = {}, this.$.page0.setContent(""), this.$.page1.setContent(""); -}, -invalidateMetrics: function() { -this.pageHeights = [], this.rowHeight = 0, this.updateMetrics(); -}, -scroll: function(e, t) { -var n = this.inherited(arguments), r = this.getScrollTop(); -return this.lastPos === r ? n : (this.lastPos = r, this.update(r), this.pinnedReorderMode && this.reorderScroll(e, t), n); -}, -setScrollTop: function(e) { -this.update(e), this.inherited(arguments), this.twiddle(); -}, -getScrollPosition: function() { -return this.calcPos(this.getScrollTop()); -}, -setScrollPosition: function(e) { -this.setScrollTop(this.calcPos(e)); -}, -scrollToBottom: function() { -this.update(this.getScrollBounds().maxTop), this.inherited(arguments); -}, -scrollToRow: function(e) { -var t = this.pageForRow(e), n = e % this.rowsPerPage, r = this.pageToPosition(t); -this.updateForPosition(r), r = this.pageToPosition(t), this.setScrollPosition(r); -if (t == this.p0 || t == this.p1) { -var i = this.$.generator.fetchRowNode(e); -if (i) { -var s = i.offsetTop; -this.bottomUp && (s = this.getPageHeight(t) - i.offsetHeight - s); -var o = this.getScrollPosition() + s; -this.setScrollPosition(o); -} -} -}, -scrollToStart: function() { -this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); -}, -scrollToEnd: function() { -this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); -}, -refresh: function() { -this.invalidatePages(), this.update(this.getScrollTop()), this.stabilize(), enyo.platform.android === 4 && this.twiddle(); -}, -reset: function() { -this.getSelection().clear(), this.invalidateMetrics(), this.invalidatePages(), this.stabilize(), this.scrollToStart(); -}, -getSelection: function() { -return this.$.generator.getSelection(); -}, -select: function(e, t) { -return this.getSelection().select(e, t); -}, -deselect: function(e) { -return this.getSelection().deselect(e); -}, -isSelected: function(e) { -return this.$.generator.isSelected(e); -}, -renderRow: function(e) { -this.$.generator.renderRow(e); -}, -rowRendered: function(e, t) { -this.updateRowBounds(t.rowIndex); -}, -prepareRow: function(e) { -this.$.generator.prepareRow(e); -}, -lockRow: function() { -this.$.generator.lockRow(); -}, -performOnRow: function(e, t, n) { -this.$.generator.performOnRow(e, t, n); -}, -animateFinish: function(e) { -return this.twiddle(), !0; -}, -twiddle: function() { -var e = this.getStrategy(); -enyo.call(e, "twiddle"); -}, -pageForPageNumber: function(e, t) { -return e % 2 === 0 ? !t || e === this.p0 ? this.$.page0 : null : !t || e === this.p1 ? this.$.page1 : null; -}, -shouldStartReordering: function(e, t) { -return !!this.getReorderable() && t.rowIndex >= 0 && !this.pinnedReorderMode && e === this.$.strategy && t.index >= 0 ? !0 : !1; -}, -startReordering: function(e) { -this.$.strategy.listReordering = !0, this.buildReorderContainer(), this.doSetupReorderComponents(e), this.styleReorderContainer(e), this.draggingRowIndex = this.placeholderRowIndex = e.rowIndex, this.draggingRowNode = e.target, this.removedInitialPage = !1, this.itemMoved = !1, this.initialPageNumber = this.currentPageNumber = this.pageForRow(e.rowIndex), this.prevScrollTop = this.getScrollTop(), this.replaceNodeWithPlaceholder(e.rowIndex); -}, -buildReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.reorderComponents.length; e++) this.$.reorderContainer.createComponent(this.reorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -styleReorderContainer: function(e) { -this.setItemPosition(this.$.reorderContainer, e.rowIndex), this.setItemBounds(this.$.reorderContainer, e.rowIndex), this.$.reorderContainer.setShowing(!0), this.centerReorderContainer && this.centerReorderContainerOnPointer(e); -}, -appendNodeToReorderContainer: function(e) { -this.$.reorderContainer.createComponent({ -allowHtml: !0, -content: e.innerHTML -}).render(); -}, -centerReorderContainerOnPointer: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = e.pageX - t.left - parseInt(this.$.reorderContainer.domStyles.width, 10) / 2, r = e.pageY - t.top + this.getScrollTop() - parseInt(this.$.reorderContainer.domStyles.height, 10) / 2; -this.getStrategyKind() != "ScrollStrategy" && (n -= this.getScrollLeft(), r -= this.getScrollTop()), this.positionReorderContainer(n, r); -}, -positionReorderContainer: function(e, t) { -this.$.reorderContainer.addClass("enyo-animatedTopAndLeft"), this.$.reorderContainer.addStyles("left:" + e + "px;top:" + t + "px;"), this.setPositionReorderContainerTimeout(); -}, -setPositionReorderContainerTimeout: function() { -this.clearPositionReorderContainerTimeout(), this.positionReorderContainerTimeout = setTimeout(enyo.bind(this, function() { -this.$.reorderContainer.removeClass("enyo-animatedTopAndLeft"), this.clearPositionReorderContainerTimeout(); -}), 100); -}, -clearPositionReorderContainerTimeout: function() { -this.positionReorderContainerTimeout && (clearTimeout(this.positionReorderContainerTimeout), this.positionReorderContainerTimeout = null); -}, -shouldDoReorderDrag: function() { -return !this.getReorderable() || this.draggingRowIndex < 0 || this.pinnedReorderMode ? !1 : !0; -}, -reorderDrag: function(e) { -this.positionReorderNode(e), this.checkForAutoScroll(e), this.updatePlaceholderPosition(e.pageY); -}, -updatePlaceholderPosition: function(e) { -var t = this.getRowIndexFromCoordinate(e); -t !== -1 && (t >= this.placeholderRowIndex ? this.movePlaceholderToIndex(Math.min(this.count, t + 1)) : this.movePlaceholderToIndex(t)); -}, -positionReorderNode: function(e) { -var t = this.$.reorderContainer.getBounds(), n = t.left + e.ddx, r = t.top + e.ddy; -r = this.getStrategyKind() == "ScrollStrategy" ? r + (this.getScrollTop() - this.prevScrollTop) : r, this.$.reorderContainer.addStyles("top: " + r + "px ; left: " + n + "px"), this.prevScrollTop = this.getScrollTop(); -}, -checkForAutoScroll: function(e) { -var t = enyo.dom.calcNodePosition(this.hasNode()), n = this.getBounds(), r; -this.autoscrollPageY = e.pageY, e.pageY - t.top < n.height * this.dragToScrollThreshold ? (r = 100 * (1 - (e.pageY - t.top) / (n.height * this.dragToScrollThreshold)), this.scrollDistance = -1 * r) : e.pageY - t.top > n.height * (1 - this.dragToScrollThreshold) ? (r = 100 * ((e.pageY - t.top - n.height * (1 - this.dragToScrollThreshold)) / (n.height - n.height * (1 - this.dragToScrollThreshold))), this.scrollDistance = 1 * r) : this.scrollDistance = 0, this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(); -}, -stopAutoScrolling: function() { -this.autoScrollTimeout && (clearTimeout(this.autoScrollTimeout), this.autoScrollTimeout = null); -}, -startAutoScrolling: function() { -this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); -}, -autoScroll: function() { -this.scrollDistance === 0 ? this.stopAutoScrolling() : this.autoScrollTimeout || this.startAutoScrolling(), this.setScrollPosition(this.getScrollPosition() + this.scrollDistance), this.positionReorderNode({ -ddx: 0, -ddy: 0 -}), this.updatePlaceholderPosition(this.autoscrollPageY); -}, -movePlaceholderToIndex: function(e) { -var t, n; -if (e < 0) return; -e >= this.count ? (t = null, n = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode()) : (t = this.$.generator.fetchRowNode(e), n = t.parentNode); -var r = this.pageForRow(e); -r >= this.pageCount && (r = this.currentPageNumber), n.insertBefore(this.placeholderNode, t), this.currentPageNumber !== r && (this.updatePageHeight(this.currentPageNumber), this.updatePageHeight(r), this.updatePagePositions(r)), this.placeholderRowIndex = e, this.currentPageNumber = r, this.itemMoved = !0; -}, -finishReordering: function(e, t) { -if (!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) return; -return this.stopAutoScrolling(), this.$.strategy.listReordering = !1, this.moveReorderedContainerToDroppedPosition(t), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, t), 100), t.preventDefault(), !0; -}, -moveReorderedContainerToDroppedPosition: function() { -var e = this.getRelativeOffset(this.placeholderNode, this.hasNode()), t = this.getStrategyKind() == "ScrollStrategy" ? e.top : e.top - this.getScrollTop(), n = e.left - this.getScrollLeft(); -this.positionReorderContainer(n, t); -}, -completeFinishReordering: function(e) { -this.completeReorderTimeout = null, this.placeholderRowIndex > this.draggingRowIndex && (this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1)); -if (this.draggingRowIndex == this.placeholderRowIndex && this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { -this.beginPinnedReorder(e); -return; -} -this.removeDraggingRowNode(), this.removePlaceholderNode(), this.emptyAndHideReorderContainer(), this.pinnedReorderMode = !1, this.reorderRows(e), this.draggingRowIndex = this.placeholderRowIndex = -1, this.refresh(); -}, -beginPinnedReorder: function(e) { -this.buildPinnedReorderContainer(), this.doSetupPinnedReorderComponents(enyo.mixin(e, { -index: this.draggingRowIndex -})), this.pinnedReorderMode = !0, this.initialPinPosition = e.pageY; -}, -emptyAndHideReorderContainer: function() { -this.$.reorderContainer.destroyComponents(), this.$.reorderContainer.setShowing(!1); -}, -buildPinnedReorderContainer: function() { -this.$.reorderContainer.destroyClientControls(); -for (var e = 0; e < this.pinnedReorderComponents.length; e++) this.$.reorderContainer.createComponent(this.pinnedReorderComponents[e], { -owner: this.owner -}); -this.$.reorderContainer.render(); -}, -reorderRows: function(e) { -this.doReorder(this.makeReorderEvent(e)), this.positionReorderedNode(), this.updateListIndices(); -}, -makeReorderEvent: function(e) { -return e.reorderFrom = this.draggingRowIndex, e.reorderTo = this.placeholderRowIndex, e; -}, -positionReorderedNode: function() { -if (!this.removedInitialPage) { -var e = this.$.generator.fetchRowNode(this.placeholderRowIndex); -e && (e.parentNode.insertBefore(this.hiddenNode, e), this.showNode(this.hiddenNode)), this.hiddenNode = null; -if (this.currentPageNumber != this.initialPageNumber) { -var t, n, r = this.pageForPageNumber(this.currentPageNumber), i = this.pageForPageNumber(this.currentPageNumber + 1); -this.initialPageNumber < this.currentPageNumber ? (t = r.hasNode().firstChild, i.hasNode().appendChild(t)) : (t = r.hasNode().lastChild, n = i.hasNode().firstChild, i.hasNode().insertBefore(t, n)), this.correctPageHeights(), this.updatePagePositions(this.initialPageNumber); -} -} -}, -updateListIndices: function() { -if (this.shouldDoRefresh()) { -this.refresh(), this.correctPageHeights(); -return; -} -var e = Math.min(this.draggingRowIndex, this.placeholderRowIndex), t = Math.max(this.draggingRowIndex, this.placeholderRowIndex), n = this.draggingRowIndex - this.placeholderRowIndex > 0 ? 1 : -1, r, i, s, o; -if (n === 1) { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", "reordered"); -for (i = t - 1, s = t; i >= e; i--) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o + 1, r.setAttribute("data-enyo-index", s); -} -r = this.hasNode().querySelector('[data-enyo-index="reordered"]'), r.setAttribute("data-enyo-index", this.placeholderRowIndex); -} else { -r = this.$.generator.fetchRowNode(this.draggingRowIndex), r && r.setAttribute("data-enyo-index", this.placeholderRowIndex); -for (i = e + 1, s = e; i <= t; i++) { -r = this.$.generator.fetchRowNode(i); -if (!r) continue; -o = parseInt(r.getAttribute("data-enyo-index"), 10), s = o - 1, r.setAttribute("data-enyo-index", s); -} -} -}, -shouldDoRefresh: function() { -return Math.abs(this.initialPageNumber - this.currentPageNumber) > 1; -}, -getNodeStyle: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) return; -var n = this.getRelativeOffset(t, this.hasNode()), r = enyo.dom.getBounds(t); -return { -h: r.height, -w: r.width, -left: n.left, -top: n.top -}; -}, -getRelativeOffset: function(e, t) { -var n = { -top: 0, -left: 0 -}; -if (e !== t && e.parentNode) do n.top += e.offsetTop || 0, n.left += e.offsetLeft || 0, e = e.offsetParent; while (e && e !== t); -return n; -}, -replaceNodeWithPlaceholder: function(e) { -var t = this.$.generator.fetchRowNode(e); -if (!t) { -enyo.log("No node - " + e); -return; -} -this.placeholderNode = this.createPlaceholderNode(t), this.hiddenNode = this.hideNode(t); -var n = this.pageForPageNumber(this.currentPageNumber); -n.hasNode().insertBefore(this.placeholderNode, this.hiddenNode); -}, -createPlaceholderNode: function(e) { -var t = this.$.placeholder.hasNode().cloneNode(!0), n = enyo.dom.getBounds(e); -return t.style.height = n.height + "px", t.style.width = n.width + "px", t; -}, -removePlaceholderNode: function() { -this.removeNode(this.placeholderNode), this.placeholderNode = null; -}, -removeDraggingRowNode: function() { -this.draggingRowNode = null; -var e = this.$.holdingarea.hasNode(); -e.innerHTML = ""; -}, -removeNode: function(e) { -if (!e || !e.parentNode) return; -e.parentNode.removeChild(e); -}, -updatePageHeight: function(e) { -if (e < 0) return; -var t = this.pageForPageNumber(e, !0); -if (t) { -var n = this.pageHeights[e], r = Math.max(1, t.getBounds().height); -this.pageHeights[e] = r, this.portSize += r - n; -} -}, -updatePagePositions: function(e) { -this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)), this.positionPage(e, this.pageForPageNumber(e)); -}, -correctPageHeights: function() { -this.updatePageHeight(this.currentPageNumber), this.initialPageNumber != this.currentPageNumber && this.updatePageHeight(this.initialPageNumber); -}, -hideNode: function(e) { -return e.style.display = "none", e; -}, -showNode: function(e) { -return e.style.display = "block", e; -}, -dropPinnedRow: function(e) { -this.moveReorderedContainerToDroppedPosition(e), this.completeReorderTimeout = setTimeout(enyo.bind(this, this.completeFinishReordering, e), 100); -return; -}, -cancelPinnedMode: function(e) { -this.placeholderRowIndex = this.draggingRowIndex, this.dropPinnedRow(e); -}, -getRowIndexFromCoordinate: function(e) { -var t = this.getScrollTop() + e - enyo.dom.calcNodePosition(this.hasNode()).top; -if (t < 0) return -1; -var n = this.positionToPageInfo(t), r = n.no == this.p0 ? this.p0RowBounds : this.p1RowBounds; -if (!r) return this.count; -var i = n.pos, s = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0, o = 0; -for (var u = n.startRow; u <= n.endRow; ++u) { -if (u === this.placeholderRowIndex) { -o += s; -if (o >= i) return -1; -} -if (u !== this.draggingRowIndex) { -o += r[u].height; -if (o >= i) return u; -} -} -return u; -}, -getIndexPosition: function(e) { -return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(e)); -}, -setItemPosition: function(e, t) { -var n = this.getNodeStyle(t), r = this.getStrategyKind() == "ScrollStrategy" ? n.top : n.top - this.getScrollTop(), i = "top:" + r + "px; left:" + n.left + "px;"; -e.addStyles(i); -}, -setItemBounds: function(e, t) { -var n = this.getNodeStyle(t), r = "width:" + n.w + "px; height:" + n.h + "px;"; -e.addStyles(r); -}, -reorderScroll: function(e, t) { -this.getStrategyKind() == "ScrollStrategy" && this.$.reorderContainer.addStyles("top:" + (this.initialPinPosition + this.getScrollTop() - this.rowHeight) + "px;"), this.updatePlaceholderPosition(this.initialPinPosition); -}, -hideReorderingRow: function() { -var e = this.hasNode().querySelector('[data-enyo-index="' + this.draggingRowIndex + '"]'); -e && (this.hiddenNode = this.hideNode(e)); -}, -isReordering: function() { -return this.draggingRowIndex > -1; -}, -isSwiping: function() { -return this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null; -}, -swipeDragStart: function(e, t) { -return t.index == null || t.vertical ? !0 : (this.completeSwipeTimeout && this.completeSwipe(t), this.swipeComplete = !1, this.swipeIndex != t.index && (this.clearSwipeables(), this.swipeIndex = t.index), this.swipeDirection = t.xDirection, this.persistentItemVisible || this.startSwipe(t), this.draggedXDistance = 0, this.draggedYDistance = 0, !0); -}, -swipeDrag: function(e, t) { -return this.persistentItemVisible ? (this.dragPersistentItem(t), this.preventDragPropagation) : this.isSwiping() ? (this.dragSwipeableComponents(this.calcNewDragPosition(t.ddx)), this.draggedXDistance = t.dx, this.draggedYDistance = t.dy, !0) : !1; -}, -swipeDragFinish: function(e, t) { -if (this.persistentItemVisible) this.dragFinishPersistentItem(t); else { -if (!this.isSwiping()) return !1; -var n = this.calcPercentageDragged(this.draggedXDistance); -n > this.percentageDraggedThreshold && t.xDirection === this.swipeDirection ? this.swipe(this.fastSwipeSpeedMS) : this.backOutSwipe(t); -} -return this.preventDragPropagation; -}, -isSwipeable: function() { -return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && !this.isReordering() && !this.pinnedReorderMode; -}, -positionSwipeableContainer: function(e, t) { -var n = this.$.generator.fetchRowNode(e); -if (!n) return; -var r = this.getRelativeOffset(n, this.hasNode()), i = enyo.dom.getBounds(n), s = t == 1 ? -1 * i.width : i.width; -this.$.swipeableComponents.addStyles("top: " + r.top + "px; left: " + s + "px; height: " + i.height + "px; width: " + i.width + "px;"); -}, -calcNewDragPosition: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = t.left, r = this.$.swipeableComponents.getBounds(), i = this.swipeDirection == 1 ? 0 : -1 * r.width, s = this.swipeDirection == 1 ? n + e > i ? i : n + e : n + e < i ? i : n + e; -return s; -}, -dragSwipeableComponents: function(e) { -this.$.swipeableComponents.applyStyle("left", e + "px"); -}, -startSwipe: function(e) { -e.index = this.swipeIndex, this.positionSwipeableContainer(this.swipeIndex, e.xDirection), this.$.swipeableComponents.setShowing(!0), this.setPersistentItemOrigin(e.xDirection), this.doSetupSwipeItem(e); -}, -dragPersistentItem: function(e) { -var t = 0, n = this.persistentItemOrigin == "right" ? Math.max(t, t + e.dx) : Math.min(t, t + e.dx); -this.$.swipeableComponents.applyStyle("left", n + "px"); -}, -dragFinishPersistentItem: function(e) { -var t = this.calcPercentageDragged(e.dx) > .2, n = e.dx > 0 ? "right" : e.dx < 0 ? "left" : null; -this.persistentItemOrigin == n ? t ? this.slideAwayItem() : this.bounceItem(e) : this.bounceItem(e); -}, -setPersistentItemOrigin: function(e) { -this.persistentItemOrigin = e == 1 ? "left" : "right"; -}, -calcPercentageDragged: function(e) { -return Math.abs(e / this.$.swipeableComponents.getBounds().width); -}, -swipe: function(e) { -this.swipeComplete = !0, this.animateSwipe(0, e); -}, -backOutSwipe: function(e) { -var t = this.$.swipeableComponents.getBounds(), n = this.swipeDirection == 1 ? -1 * t.width : t.width; -this.animateSwipe(n, this.fastSwipeSpeedMS), this.swipeDirection = null; -}, -bounceItem: function(e) { -var t = this.$.swipeableComponents.getBounds(); -t.left != t.width && this.animateSwipe(0, this.normalSwipeSpeedMS); -}, -slideAwayItem: function() { -var e = this.$.swipeableComponents, t = e.getBounds().width, n = this.persistentItemOrigin == "left" ? -1 * t : t; -this.animateSwipe(n, this.normalSwipeSpeedMS), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -clearSwipeables: function() { -this.$.swipeableComponents.setShowing(!1), this.persistentItemVisible = !1, this.setPersistSwipeableItem(!1); -}, -completeSwipe: function(e) { -this.completeSwipeTimeout && (clearTimeout(this.completeSwipeTimeout), this.completeSwipeTimeout = null), this.getPersistSwipeableItem() ? this.persistentItemVisible = !0 : (this.$.swipeableComponents.setShowing(!1), this.swipeComplete && this.doSwipeComplete({ -index: this.swipeIndex, -xDirection: this.swipeDirection -})), this.swipeIndex = null, this.swipeDirection = null; -}, -animateSwipe: function(e, t) { -var n = enyo.now(), r = 0, i = this.$.swipeableComponents, s = parseInt(i.domStyles.left, 10), o = e - s; -this.stopAnimateSwipe(); -var u = enyo.bind(this, function() { -var e = enyo.now() - n, r = e / t, a = s + o * Math.min(r, 1); -i.applyStyle("left", a + "px"), this.job = enyo.requestAnimationFrame(u), e / t >= 1 && (this.stopAnimateSwipe(), this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { -this.completeSwipe(); -}), this.completeSwipeDelayMS)); -}); -this.job = enyo.requestAnimationFrame(u); -}, -stopAnimateSwipe: function() { -this.job && (this.job = enyo.cancelRequestAnimationFrame(this.job)); -} -}); - -// PulldownList.js - -enyo.kind({ -name: "enyo.PulldownList", -kind: "List", -touch: !0, -pully: null, -pulldownTools: [ { -name: "pulldown", -classes: "enyo-list-pulldown", -components: [ { -name: "puller", -kind: "Puller" -} ] -} ], -events: { -onPullStart: "", -onPullCancel: "", -onPull: "", -onPullRelease: "", -onPullComplete: "" -}, -handlers: { -onScrollStart: "scrollStartHandler", -onScrollStop: "scrollStopHandler", -ondragfinish: "dragfinish" -}, -pullingMessage: "Pull down to refresh...", -pulledMessage: "Release to refresh...", -loadingMessage: "Loading...", -pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", -pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", -loadingIconClass: "", -create: function() { -var e = { -kind: "Puller", -showing: !1, -text: this.loadingMessage, -iconClass: this.loadingIconClass, -onCreate: "setPully" -}; -this.listTools.splice(0, 0, e), this.inherited(arguments), this.setPulling(); -}, -initComponents: function() { -this.createChrome(this.pulldownTools), this.accel = enyo.dom.canAccelerate(), this.translation = this.accel ? "translate3d" : "translate", this.strategyKind = this.resetStrategyKind(), this.inherited(arguments); -}, -resetStrategyKind: function() { -return enyo.platform.android >= 3 ? "TranslateScrollStrategy" : "TouchScrollStrategy"; -}, -setPully: function(e, t) { -this.pully = t.originator; -}, -scrollStartHandler: function() { -this.firedPullStart = !1, this.firedPull = !1, this.firedPullCancel = !1; -}, -scroll: function(e, t) { -var n = this.inherited(arguments); -this.completingPull && this.pully.setShowing(!1); -var r = this.getStrategy().$.scrollMath || this.getStrategy(), i = -1 * this.getScrollTop(); -return r.isInOverScroll() && i > 0 && (enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + i + "px" + (this.accel ? ",0" : "")), this.firedPullStart || (this.firedPullStart = !0, this.pullStart(), this.pullHeight = this.$.pulldown.getBounds().height), i > this.pullHeight && !this.firedPull && (this.firedPull = !0, this.firedPullCancel = !1, this.pull()), this.firedPull && !this.firedPullCancel && i < this.pullHeight && (this.firedPullCancel = !0, this.firedPull = !1, this.pullCancel())), n; -}, -scrollStopHandler: function() { -this.completingPull && (this.completingPull = !1, this.doPullComplete()); -}, -dragfinish: function() { -if (this.firedPull) { -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(-1 * this.getScrollTop() - this.pullHeight), this.pullRelease(); -} -}, -completePull: function() { -this.completingPull = !0; -var e = this.getStrategy().$.scrollMath || this.getStrategy(); -e.setScrollY(this.pullHeight), e.start(); -}, -pullStart: function() { -this.setPulling(), this.pully.setShowing(!1), this.$.puller.setShowing(!0), this.doPullStart(); -}, -pull: function() { -this.setPulled(), this.doPull(); -}, -pullCancel: function() { -this.setPulling(), this.doPullCancel(); -}, -pullRelease: function() { -this.$.puller.setShowing(!1), this.pully.setShowing(!0), this.doPullRelease(); -}, -setPulling: function() { -this.$.puller.setText(this.pullingMessage), this.$.puller.setIconClass(this.pullingIconClass); -}, -setPulled: function() { -this.$.puller.setText(this.pulledMessage), this.$.puller.setIconClass(this.pulledIconClass); -} -}), enyo.kind({ -name: "enyo.Puller", -classes: "enyo-puller", -published: { -text: "", -iconClass: "" -}, -events: { -onCreate: "" -}, -components: [ { -name: "icon" -}, { -name: "text", -tag: "span", -classes: "enyo-puller-text" -} ], -create: function() { -this.inherited(arguments), this.doCreate(), this.textChanged(), this.iconClassChanged(); -}, -textChanged: function() { -this.$.text.setContent(this.text); -}, -iconClassChanged: function() { -this.$.icon.setClasses(this.iconClass); -} -}); - -// AroundList.js - -enyo.kind({ -name: "enyo.AroundList", -kind: "enyo.List", -listTools: [ { -name: "port", -classes: "enyo-list-port enyo-border-box", -components: [ { -name: "aboveClient" -}, { -name: "generator", -kind: "FlyweightRepeater", -canGenerate: !1, -components: [ { -tag: null, -name: "client" -} ] -}, { -name: "holdingarea", -allowHtml: !0, -classes: "enyo-list-holdingarea" -}, { -name: "page0", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "page1", -allowHtml: !0, -classes: "enyo-list-page" -}, { -name: "belowClient" -}, { -name: "placeholder" -}, { -name: "swipeableComponents", -style: "position:absolute; display:block; top:-1000px; left:0px;" -} ] -} ], -aboveComponents: null, -initComponents: function() { -this.inherited(arguments), this.aboveComponents && this.$.aboveClient.createComponents(this.aboveComponents, { -owner: this.owner -}), this.belowComponents && this.$.belowClient.createComponents(this.belowComponents, { -owner: this.owner -}); -}, -updateMetrics: function() { -this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100), this.pageCount = Math.ceil(this.count / this.rowsPerPage), this.aboveHeight = this.$.aboveClient.getBounds().height, this.belowHeight = this.$.belowClient.getBounds().height, this.portSize = this.aboveHeight + this.belowHeight; -for (var e = 0; e < this.pageCount; e++) this.portSize += this.getPageHeight(e); -this.adjustPortSize(); -}, -positionPage: function(e, t) { -t.pageNo = e; -var n = this.pageToPosition(e), r = this.bottomUp ? this.belowHeight : this.aboveHeight; -n += r, t.applyStyle(this.pageBound, n + "px"); -}, -scrollToContentStart: function() { -var e = this.bottomUp ? this.belowHeight : this.aboveHeight; -this.setScrollPosition(e); -} -}); - -// Slideable.js - -enyo.kind({ -name: "enyo.Slideable", -kind: "Control", -published: { -axis: "h", -value: 0, -unit: "px", -min: 0, -max: 0, -accelerated: "auto", -overMoving: !0, -draggable: !0 -}, -events: { -onAnimateFinish: "", -onChange: "" -}, -preventDragPropagation: !1, -tools: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorComplete" -} ], -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -kDragScalar: 1, -dragEventProp: "dx", -unitModifier: !1, -canTransform: !1, -create: function() { -this.inherited(arguments), this.acceleratedChanged(), this.transformChanged(), this.axisChanged(), this.valueChanged(), this.addClass("enyo-slideable"); -}, -initComponents: function() { -this.createComponents(this.tools), this.inherited(arguments); -}, -rendered: function() { -this.inherited(arguments), this.canModifyUnit(), this.updateDragScalar(); -}, -resizeHandler: function() { -this.inherited(arguments), this.updateDragScalar(); -}, -canModifyUnit: function() { -if (!this.canTransform) { -var e = this.getInitialStyleValue(this.hasNode(), this.boundary); -e.match(/px/i) && this.unit === "%" && (this.unitModifier = this.getBounds()[this.dimension]); -} -}, -getInitialStyleValue: function(e, t) { -var n = enyo.dom.getComputedStyle(e); -return n ? n.getPropertyValue(t) : e && e.currentStyle ? e.currentStyle[t] : "0"; -}, -updateBounds: function(e, t) { -var n = {}; -n[this.boundary] = e, this.setBounds(n, this.unit), this.setInlineStyles(e, t); -}, -updateDragScalar: function() { -if (this.unit == "%") { -var e = this.getBounds()[this.dimension]; -this.kDragScalar = e ? 100 / e : 1, this.canTransform || this.updateBounds(this.value, 100); -} -}, -transformChanged: function() { -this.canTransform = enyo.dom.canTransform(); -}, -acceleratedChanged: function() { -enyo.platform.android > 2 || enyo.dom.accelerate(this, this.accelerated); -}, -axisChanged: function() { -var e = this.axis == "h"; -this.dragMoveProp = e ? "dx" : "dy", this.shouldDragProp = e ? "horizontal" : "vertical", this.transform = e ? "translateX" : "translateY", this.dimension = e ? "width" : "height", this.boundary = e ? "left" : "top"; -}, -setInlineStyles: function(e, t) { -var n = {}; -this.unitModifier ? (n[this.boundary] = this.percentToPixels(e, this.unitModifier), n[this.dimension] = this.unitModifier, this.setBounds(n)) : (t ? n[this.dimension] = t : n[this.boundary] = e, this.setBounds(n, this.unit)); -}, -valueChanged: function(e) { -var t = this.value; -this.isOob(t) && !this.isAnimating() && (this.value = this.overMoving ? this.dampValue(t) : this.clampValue(t)), enyo.platform.android > 2 && (this.value ? (e === 0 || e === undefined) && enyo.dom.accelerate(this, this.accelerated) : enyo.dom.accelerate(this, !1)), this.canTransform ? enyo.dom.transformValue(this, this.transform, this.value + this.unit) : this.setInlineStyles(this.value, !1), this.doChange(); -}, -getAnimator: function() { -return this.$.animator; -}, -isAtMin: function() { -return this.value <= this.calcMin(); -}, -isAtMax: function() { -return this.value >= this.calcMax(); -}, -calcMin: function() { -return this.min; -}, -calcMax: function() { -return this.max; -}, -clampValue: function(e) { -var t = this.calcMin(), n = this.calcMax(); -return Math.max(t, Math.min(e, n)); -}, -dampValue: function(e) { -return this.dampBound(this.dampBound(e, this.min, 1), this.max, -1); -}, -dampBound: function(e, t, n) { -var r = e; -return r * n < t * n && (r = t + (r - t) / 4), r; -}, -percentToPixels: function(e, t) { -return Math.floor(t / 100 * e); -}, -pixelsToPercent: function(e) { -var t = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; -return e / t * 100; -}, -shouldDrag: function(e) { -return this.draggable && e[this.shouldDragProp]; -}, -isOob: function(e) { -return e > this.calcMax() || e < this.calcMin(); -}, -dragstart: function(e, t) { -if (this.shouldDrag(t)) return t.preventDefault(), this.$.animator.stop(), t.dragInfo = {}, this.dragging = !0, this.drag0 = this.value, this.dragd0 = 0, this.preventDragPropagation; -}, -drag: function(e, t) { -if (this.dragging) { -t.preventDefault(); -var n = this.canTransform ? t[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(t[this.dragMoveProp]), r = this.drag0 + n, i = n - this.dragd0; -return this.dragd0 = n, i && (t.dragInfo.minimizing = i < 0), this.setValue(r), this.preventDragPropagation; -} -}, -dragfinish: function(e, t) { -if (this.dragging) return this.dragging = !1, this.completeDrag(t), t.preventTap(), this.preventDragPropagation; -}, -completeDrag: function(e) { -this.value !== this.calcMax() && this.value != this.calcMin() && this.animateToMinMax(e.dragInfo.minimizing); -}, -isAnimating: function() { -return this.$.animator.isAnimating(); -}, -play: function(e, t) { -this.$.animator.play({ -startValue: e, -endValue: t, -node: this.hasNode() -}); -}, -animateTo: function(e) { -this.play(this.value, e); -}, -animateToMin: function() { -this.animateTo(this.calcMin()); -}, -animateToMax: function() { -this.animateTo(this.calcMax()); -}, -animateToMinMax: function(e) { -e ? this.animateToMin() : this.animateToMax(); -}, -animatorStep: function(e) { -return this.setValue(e.value), !0; -}, -animatorComplete: function(e) { -return this.doAnimateFinish(e), !0; -}, -toggleMinMax: function() { -this.animateToMinMax(!this.isAtMin()); -} -}); - -// Arranger.js - -enyo.kind({ -name: "enyo.Arranger", -kind: "Layout", -layoutClass: "enyo-arranger", -accelerated: "auto", -dragProp: "ddx", -dragDirectionProp: "xDirection", -canDragProp: "horizontal", -incrementalPoints: !1, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n._arranger = null; -this.inherited(arguments); -}, -arrange: function(e, t) {}, -size: function() {}, -start: function() { -var e = this.container.fromIndex, t = this.container.toIndex, n = this.container.transitionPoints = [ e ]; -if (this.incrementalPoints) { -var r = Math.abs(t - e) - 2, i = e; -while (r >= 0) i += t < e ? -1 : 1, n.push(i), r--; -} -n.push(this.container.toIndex); -}, -finish: function() {}, -calcArrangementDifference: function(e, t, n, r) {}, -canDragEvent: function(e) { -return e[this.canDragProp]; -}, -calcDragDirection: function(e) { -return e[this.dragDirectionProp]; -}, -calcDrag: function(e) { -return e[this.dragProp]; -}, -drag: function(e, t, n, r, i) { -var s = this.measureArrangementDelta(-e, t, n, r, i); -return s; -}, -measureArrangementDelta: function(e, t, n, r, i) { -var s = this.calcArrangementDifference(t, n, r, i), o = s ? e / Math.abs(s) : 0; -return o *= this.container.fromIndex > this.container.toIndex ? -1 : 1, o; -}, -_arrange: function(e) { -this.containerBounds || this.reflow(); -var t = this.getOrderedControls(e); -this.arrange(t, e); -}, -arrangeControl: function(e, t) { -e._arranger = enyo.mixin(e._arranger || {}, t); -}, -flow: function() { -this.c$ = [].concat(this.container.getPanels()), this.controlsIndex = 0; -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) { -enyo.dom.accelerate(n, this.accelerated); -if (enyo.platform.safari) { -var r = n.children; -for (var i = 0, s; s = r[i]; i++) enyo.dom.accelerate(s, this.accelerated); -} -} -}, -reflow: function() { -var e = this.container.hasNode(); -this.containerBounds = e ? { -width: e.clientWidth, -height: e.clientHeight -} : {}, this.size(); -}, -flowArrangement: function() { -var e = this.container.arrangement; -if (e) for (var t = 0, n = this.container.getPanels(), r; r = n[t]; t++) this.flowControl(r, e[t]); -}, -flowControl: function(e, t) { -enyo.Arranger.positionControl(e, t); -var n = t.opacity; -n != null && enyo.Arranger.opacifyControl(e, n); -}, -getOrderedControls: function(e) { -var t = Math.floor(e), n = t - this.controlsIndex, r = n > 0, i = this.c$ || []; -for (var s = 0; s < Math.abs(n); s++) r ? i.push(i.shift()) : i.unshift(i.pop()); -return this.controlsIndex = t, i; -}, -statics: { -positionControl: function(e, t, n) { -var r = n || "px"; -if (!this.updating) if (enyo.dom.canTransform() && !enyo.platform.android && enyo.platform.ie !== 10) { -var i = t.left, s = t.top; -i = enyo.isString(i) ? i : i && i + r, s = enyo.isString(s) ? s : s && s + r, enyo.dom.transform(e, { -translateX: i || null, -translateY: s || null -}); -} else e.setBounds(t, n); -}, -opacifyControl: function(e, t) { -var n = t; -n = n > .99 ? 1 : n < .01 ? 0 : n, enyo.platform.ie < 9 ? e.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + n * 100 + ")") : e.applyStyle("opacity", n); -} -} -}); - -// CardArranger.js - -enyo.kind({ -name: "enyo.CardArranger", -kind: "Arranger", -layoutClass: "enyo-arranger enyo-arranger-fit", -calcArrangementDifference: function(e, t, n, r) { -return this.containerBounds.width; -}, -arrange: function(e, t) { -for (var n = 0, r, i, s; r = e[n]; n++) s = n === 0 ? 1 : 0, this.arrangeControl(r, { -opacity: s -}); -}, -start: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.opacifyControl(n, 1), n.showing || n.setShowing(!0); -this.inherited(arguments); -} -}); - -// CardSlideInArranger.js - -enyo.kind({ -name: "enyo.CardSlideInArranger", -kind: "CardArranger", -start: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) { -var r = n.showing; -n.setShowing(t == this.container.fromIndex || t == this.container.toIndex), n.showing && !r && n.resized(); -} -var i = this.container.fromIndex; -t = this.container.toIndex, this.container.transitionPoints = [ t + "." + i + ".s", t + "." + i + ".f" ]; -}, -finish: function() { -this.inherited(arguments); -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.setShowing(t == this.container.toIndex); -}, -arrange: function(e, t) { -var n = t.split("."), r = n[0], i = n[1], s = n[2] == "s", o = this.containerBounds.width; -for (var u = 0, a = this.container.getPanels(), f, l; f = a[u]; u++) l = o, i == u && (l = s ? 0 : -o), r == u && (l = s ? o : 0), i == u && i == r && (l = 0), this.arrangeControl(f, { -left: l -}); -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null -}); -this.inherited(arguments); -} -}); - -// CarouselArranger.js - -enyo.kind({ -name: "enyo.CarouselArranger", -kind: "Arranger", -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s, o, u; -n.height -= t.top + t.bottom, n.width -= t.left + t.right; -var a; -for (r = 0, s = 0; u = e[r]; r++) o = enyo.dom.calcMarginExtents(u.hasNode()), u.width = u.getBounds().width, u.marginWidth = o.right + o.left, s += (u.fit ? 0 : u.width) + u.marginWidth, u.fit && (a = u); -if (a) { -var f = n.width - s; -a.width = f >= 0 ? f : a.width; -} -for (r = 0, i = t.left; u = e[r]; r++) u.setBounds({ -top: t.top, -bottom: t.bottom, -width: u.fit ? u.width : null -}); -}, -arrange: function(e, t) { -this.container.wrap ? this.arrangeWrap(e, t) : this.arrangeNoWrap(e, t); -}, -arrangeNoWrap: function(e, t) { -var n, r, i, s, o = this.container.getPanels(), u = this.container.clamp(t), a = this.containerBounds.width; -for (n = u, i = 0; s = o[n]; n++) { -i += s.width + s.marginWidth; -if (i > a) break; -} -var f = a - i, l = 0; -if (f > 0) { -var c = u; -for (n = u - 1, r = 0; s = o[n]; n--) { -r += s.width + s.marginWidth; -if (f - r <= 0) { -l = f - r, u = n; -break; -} -} -} -var h, p; -for (n = 0, p = this.containerPadding.left + l; s = o[n]; n++) h = s.width + s.marginWidth, n < u ? this.arrangeControl(s, { -left: -h -}) : (this.arrangeControl(s, { -left: Math.floor(p) -}), p += h); -}, -arrangeWrap: function(e, t) { -for (var n = 0, r = this.containerPadding.left, i, s; s = e[n]; n++) this.arrangeControl(s, { -left: r -}), r += s.width + s.marginWidth; -}, -calcArrangementDifference: function(e, t, n, r) { -var i = Math.abs(e % this.c$.length); -return t[i].left - r[i].left; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// CollapsingArranger.js - -enyo.kind({ -name: "enyo.CollapsingArranger", -kind: "CarouselArranger", -peekWidth: 0, -size: function() { -this.clearLastSize(), this.inherited(arguments); -}, -clearLastSize: function() { -for (var e = 0, t = this.container.getPanels(), n; n = t[e]; e++) n._fit && e != t.length - 1 && (n.applyStyle("width", null), n._fit = null); -}, -constructor: function() { -this.inherited(arguments), this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; -}, -arrange: function(e, t) { -var n = this.container.getPanels(); -for (var r = 0, i = this.containerPadding.left, s, o, u = 0; o = n[r]; r++) o.getShowing() ? (this.arrangeControl(o, { -left: i + u * this.peekWidth -}), r >= t && (i += o.width + o.marginWidth - this.peekWidth), u++) : (this.arrangeControl(o, { -left: i -}), r >= t && (i += o.width + o.marginWidth)), r == n.length - 1 && t < 0 && this.arrangeControl(o, { -left: i - t -}); -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels().length - 1; -return Math.abs(r[i].left - t[i].left); -}, -flowControl: function(e, t) { -this.inherited(arguments); -if (this.container.realtimeFit) { -var n = this.container.getPanels(), r = n.length - 1, i = n[r]; -e == i && this.fitControl(e, t.left); -} -}, -finish: function() { -this.inherited(arguments); -if (!this.container.realtimeFit && this.containerBounds) { -var e = this.container.getPanels(), t = this.container.arrangement, n = e.length - 1, r = e[n]; -this.fitControl(r, t[n].left); -} -}, -fitControl: function(e, t) { -e._fit = !0, e.applyStyle("width", this.containerBounds.width - t + "px"), e.resized(); -} -}); - -// DockRightArranger.js - -enyo.kind({ -name: "enyo.DockRightArranger", -kind: "Arranger", -basePanel: !1, -overlap: 0, -layoutWidth: 0, -constructor: function() { -this.inherited(arguments), this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap, this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}, n = this.containerBounds, r, i, s; -n.width -= t.left + t.right; -var o = n.width, u = e.length; -this.container.transitionPositions = {}; -for (r = 0; s = e[r]; r++) s.width = r === 0 && this.container.basePanel ? o : s.getBounds().width; -for (r = 0; s = e[r]; r++) { -r === 0 && this.container.basePanel && s.setBounds({ -width: o -}), s.setBounds({ -top: t.top, -bottom: t.bottom -}); -for (j = 0; s = e[j]; j++) { -var a; -if (r === 0 && this.container.basePanel) a = 0; else if (j < r) a = o; else { -if (r !== j) break; -var f = o > this.layoutWidth ? this.overlap : 0; -a = o - e[r].width + f; -} -this.container.transitionPositions[r + "." + j] = a; -} -if (j < u) { -var l = !1; -for (k = r + 1; k < u; k++) { -var f = 0; -if (l) f = 0; else if (e[r].width + e[k].width - this.overlap > o) f = 0, l = !0; else { -f = e[r].width - this.overlap; -for (i = r; i < k; i++) { -var c = f + e[i + 1].width - this.overlap; -if (!(c < o)) { -f = o; -break; -} -f = c; -} -f = o - f; -} -this.container.transitionPositions[r + "." + k] = f; -} -} -} -}, -arrange: function(e, t) { -var n, r, i = this.container.getPanels(), s = this.container.clamp(t); -for (n = 0; r = i[n]; n++) { -var o = this.container.transitionPositions[n + "." + s]; -this.arrangeControl(r, { -left: o -}); -} -}, -calcArrangementDifference: function(e, t, n, r) { -var i = this.container.getPanels(), s = e < n ? i[n].width : i[e].width; -return s; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("top", null), n.applyStyle("bottom", null), n.applyStyle("left", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// OtherArrangers.js - -enyo.kind({ -name: "enyo.LeftRightArranger", -kind: "Arranger", -margin: 40, -axisSize: "width", -offAxisSize: "height", -axisPosition: "left", -constructor: function() { -this.inherited(arguments), this.margin = this.container.margin != null ? this.container.margin : this.margin; -}, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds[this.axisSize], n = t - this.margin - this.margin; -for (var r = 0, i, s; s = e[r]; r++) i = {}, i[this.axisSize] = n, i[this.offAxisSize] = "100%", s.setBounds(i); -}, -start: function() { -this.inherited(arguments); -var e = this.container.fromIndex, t = this.container.toIndex, n = this.getOrderedControls(t), r = Math.floor(n.length / 2); -for (var i = 0, s; s = n[i]; i++) e > t ? i == n.length - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1) : i == n.length - 1 - r ? s.applyStyle("z-index", 0) : s.applyStyle("z-index", 1); -}, -arrange: function(e, t) { -var n, r, i, s; -if (this.container.getPanels().length == 1) { -s = {}, s[this.axisPosition] = this.margin, this.arrangeControl(this.container.getPanels()[0], s); -return; -} -var o = Math.floor(this.container.getPanels().length / 2), u = this.getOrderedControls(Math.floor(t) - o), a = this.containerBounds[this.axisSize] - this.margin - this.margin, f = this.margin - a * o; -for (n = 0; r = u[n]; n++) s = {}, s[this.axisPosition] = f, this.arrangeControl(r, s), f += a; -}, -calcArrangementDifference: function(e, t, n, r) { -if (this.container.getPanels().length == 1) return 0; -var i = Math.abs(e % this.c$.length); -return t[i][this.axisPosition] - r[i][this.axisPosition]; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), enyo.Arranger.opacifyControl(n, 1), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.TopBottomArranger", -kind: "LeftRightArranger", -dragProp: "ddy", -dragDirectionProp: "yDirection", -canDragProp: "vertical", -axisSize: "height", -offAxisSize: "width", -axisPosition: "top" -}), enyo.kind({ -name: "enyo.SpiralArranger", -kind: "Arranger", -incrementalPoints: !0, -inc: 20, -size: function() { -var e = this.container.getPanels(), t = this.containerBounds, n = this.controlWidth = t.width / 3, r = this.controlHeight = t.height / 3; -for (var i = 0, s; s = e[i]; i++) s.setBounds({ -width: n, -height: r -}); -}, -arrange: function(e, t) { -var n = this.inc; -for (var r = 0, i = e.length, s; s = e[r]; r++) { -var o = Math.cos(r / i * 2 * Math.PI) * r * n + this.controlWidth, u = Math.sin(r / i * 2 * Math.PI) * r * n + this.controlHeight; -this.arrangeControl(s, { -left: o, -top: u -}); -} -}, -start: function() { -this.inherited(arguments); -var e = this.getOrderedControls(this.container.toIndex); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", e.length - t); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.controlWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) n.applyStyle("z-index", null), enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}), enyo.kind({ -name: "enyo.GridArranger", -kind: "Arranger", -incrementalPoints: !0, -colWidth: 100, -colHeight: 100, -size: function() { -var e = this.container.getPanels(), t = this.colWidth, n = this.colHeight; -for (var r = 0, i; i = e[r]; r++) i.setBounds({ -width: t, -height: n -}); -}, -arrange: function(e, t) { -var n = this.colWidth, r = this.colHeight, i = Math.max(1, Math.floor(this.containerBounds.width / n)), s; -for (var o = 0, u = 0; u < e.length; o++) for (var a = 0; a < i && (s = e[u]); a++, u++) this.arrangeControl(s, { -left: n * a, -top: r * o -}); -}, -flowControl: function(e, t) { -this.inherited(arguments), enyo.Arranger.opacifyControl(e, t.top % this.colHeight !== 0 ? .25 : 1); -}, -calcArrangementDifference: function(e, t, n, r) { -return this.colWidth; -}, -destroy: function() { -var e = this.container.getPanels(); -for (var t = 0, n; n = e[t]; t++) enyo.Arranger.positionControl(n, { -left: null, -top: null -}), n.applyStyle("left", null), n.applyStyle("top", null), n.applyStyle("height", null), n.applyStyle("width", null); -this.inherited(arguments); -} -}); - -// Panels.js - -enyo.kind({ -name: "enyo.Panels", -classes: "enyo-panels", -published: { -index: 0, -draggable: !0, -animate: !0, -wrap: !1, -arrangerKind: "CardArranger", -narrowFit: !0 -}, -events: { -onTransitionStart: "", -onTransitionFinish: "" -}, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -onscroll: "domScroll" -}, -tools: [ { -kind: "Animator", -onStep: "step", -onEnd: "completed" -} ], -fraction: 0, -create: function() { -this.transitionPoints = [], this.inherited(arguments), this.arrangerKindChanged(), this.narrowFitChanged(), this.indexChanged(); -}, -rendered: function() { -this.inherited(arguments), enyo.makeBubble(this, "scroll"); -}, -domScroll: function(e, t) { -this.hasNode() && this.node.scrollLeft > 0 && (this.node.scrollLeft = 0); -}, -initComponents: function() { -this.createChrome(this.tools), this.inherited(arguments); -}, -arrangerKindChanged: function() { -this.setLayoutKind(this.arrangerKind); -}, -narrowFitChanged: function() { -this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); -}, -destroy: function() { -this.destroying = !0, this.inherited(arguments); -}, -removeControl: function(e) { -this.inherited(arguments), this.destroying && this.controls.length > 0 && this.isPanel(e) && (this.setIndex(Math.max(this.index - 1, 0)), this.flow(), this.reflow()); -}, -isPanel: function() { -return !0; -}, -flow: function() { -this.arrangements = [], this.inherited(arguments); -}, -reflow: function() { -this.arrangements = [], this.inherited(arguments), this.refresh(); -}, -getPanels: function() { -var e = this.controlParent || this; -return e.children; -}, -getActive: function() { -var e = this.getPanels(), t = this.index % e.length; -return t < 0 && (t += e.length), e[t]; -}, -getAnimator: function() { -return this.$.animator; -}, -setIndex: function(e) { -this.setPropertyValue("index", e, "indexChanged"); -}, -setIndexDirect: function(e) { -this.setIndex(e), this.completed(); -}, -previous: function() { -this.setIndex(this.index - 1); -}, -next: function() { -this.setIndex(this.index + 1); -}, -clamp: function(e) { -var t = this.getPanels().length - 1; -return this.wrap ? e : Math.max(0, Math.min(e, t)); -}, -indexChanged: function(e) { -this.lastIndex = e, this.index = this.clamp(this.index), !this.dragging && this.$.animator && (this.$.animator.isAnimating() && this.completed(), this.$.animator.stop(), this.hasNode() && (this.animate ? (this.startTransition(), this.$.animator.play({ -startValue: this.fraction -})) : this.refresh())); -}, -step: function(e) { -this.fraction = e.value, this.stepTransition(); -}, -completed: function() { -this.$.animator.isAnimating() && this.$.animator.stop(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -dragstart: function(e, t) { -if (this.draggable && this.layout && this.layout.canDragEvent(t)) return t.preventDefault(), this.dragstartTransition(t), this.dragging = !0, this.$.animator.stop(), !0; -}, -drag: function(e, t) { -this.dragging && (t.preventDefault(), this.dragTransition(t)); -}, -dragfinish: function(e, t) { -this.dragging && (this.dragging = !1, t.preventTap(), this.dragfinishTransition(t)); -}, -dragstartTransition: function(e) { -if (!this.$.animator.isAnimating()) { -var t = this.fromIndex = this.index; -this.toIndex = t - (this.layout ? this.layout.calcDragDirection(e) : 0); -} else this.verifyDragTransition(e); -this.fromIndex = this.clamp(this.fromIndex), this.toIndex = this.clamp(this.toIndex), this.fireTransitionStart(), this.layout && this.layout.start(); -}, -dragTransition: function(e) { -var t = this.layout ? this.layout.calcDrag(e) : 0, n = this.transitionPoints, r = n[0], i = n[n.length - 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i), u = this.layout ? this.layout.drag(t, r, s, i, o) : 0, a = t && !u; -a, this.fraction += u; -var f = this.fraction; -if (f > 1 || f < 0 || a) (f > 0 || a) && this.dragfinishTransition(e), this.dragstartTransition(e), this.fraction = 0; -this.stepTransition(); -}, -dragfinishTransition: function(e) { -this.verifyDragTransition(e), this.setIndex(this.toIndex), this.dragging && this.fireTransitionFinish(); -}, -verifyDragTransition: function(e) { -var t = this.layout ? this.layout.calcDragDirection(e) : 0, n = Math.min(this.fromIndex, this.toIndex), r = Math.max(this.fromIndex, this.toIndex); -if (t > 0) { -var i = n; -n = r, r = i; -} -n != this.fromIndex && (this.fraction = 1 - this.fraction), this.fromIndex = n, this.toIndex = r; -}, -refresh: function() { -this.$.animator && this.$.animator.isAnimating() && this.$.animator.stop(), this.startTransition(), this.fraction = 1, this.stepTransition(), this.finishTransition(); -}, -startTransition: function() { -this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0, this.toIndex = this.toIndex != null ? this.toIndex : this.index, this.layout && this.layout.start(), this.fireTransitionStart(); -}, -finishTransition: function() { -this.layout && this.layout.finish(), this.transitionPoints = [], this.fraction = 0, this.fromIndex = this.toIndex = null, this.fireTransitionFinish(); -}, -fireTransitionStart: function() { -var e = this.startTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.fromIndex || e.toIndex != this.toIndex) && (this.startTransitionInfo = { -fromIndex: this.fromIndex, -toIndex: this.toIndex -}, this.doTransitionStart(enyo.clone(this.startTransitionInfo))); -}, -fireTransitionFinish: function() { -var e = this.finishTransitionInfo; -this.hasNode() && (!e || e.fromIndex != this.lastIndex || e.toIndex != this.index) && (this.finishTransitionInfo = { -fromIndex: this.lastIndex, -toIndex: this.index -}, this.doTransitionFinish(enyo.clone(this.finishTransitionInfo))), this.lastIndex = this.index; -}, -stepTransition: function() { -if (this.hasNode()) { -var e = this.transitionPoints, t = (this.fraction || 0) * (e.length - 1), n = Math.floor(t); -t -= n; -var r = e[n], i = e[n + 1], s = this.fetchArrangement(r), o = this.fetchArrangement(i); -this.arrangement = s && o ? enyo.Panels.lerp(s, o, t) : s || o, this.arrangement && this.layout && this.layout.flowArrangement(); -} -}, -fetchArrangement: function(e) { -return e != null && !this.arrangements[e] && this.layout && (this.layout._arrange(e), this.arrangements[e] = this.readArrangement(this.getPanels())), this.arrangements[e]; -}, -readArrangement: function(e) { -var t = []; -for (var n = 0, r = e, i; i = r[n]; n++) t.push(enyo.clone(i._arranger)); -return t; -}, -statics: { -isScreenNarrow: function() { -return enyo.dom.getWindowWidth() <= 800; -}, -lerp: function(e, t, n) { -var r = []; -for (var i = 0, s = enyo.keys(e), o; o = s[i]; i++) r.push(this.lerpObject(e[o], t[o], n)); -return r; -}, -lerpObject: function(e, t, n) { -var r = enyo.clone(e), i, s; -if (t) for (var o in e) i = e[o], s = t[o], i != s && (r[o] = i - (i - s) * n); -return r; -} -} -}); - -// Node.js - -enyo.kind({ -name: "enyo.Node", -published: { -expandable: !1, -expanded: !1, -icon: "", -onlyIconExpands: !1, -selected: !1 -}, -style: "padding: 0 0 0 16px;", -content: "Node", -defaultKind: "Node", -classes: "enyo-node", -components: [ { -name: "icon", -kind: "Image", -showing: !1 -}, { -kind: "Control", -name: "caption", -Xtag: "span", -style: "display: inline-block; padding: 4px;", -allowHtml: !0 -}, { -kind: "Control", -name: "extra", -tag: "span", -allowHtml: !0 -} ], -childClient: [ { -kind: "Control", -name: "box", -classes: "enyo-node-box", -Xstyle: "border: 1px solid orange;", -components: [ { -kind: "Control", -name: "client", -classes: "enyo-node-client", -Xstyle: "border: 1px solid lightblue;" -} ] -} ], -handlers: { -ondblclick: "dblclick" -}, -events: { -onNodeTap: "nodeTap", -onNodeDblClick: "nodeDblClick", -onExpand: "nodeExpand", -onDestroyed: "nodeDestroyed" -}, -create: function() { -this.inherited(arguments), this.selectedChanged(), this.iconChanged(); -}, -destroy: function() { -this.doDestroyed(), this.inherited(arguments); -}, -initComponents: function() { -this.expandable && (this.kindComponents = this.kindComponents.concat(this.childClient)), this.inherited(arguments); -}, -contentChanged: function() { -this.$.caption.setContent(this.content); -}, -iconChanged: function() { -this.$.icon.setSrc(this.icon), this.$.icon.setShowing(Boolean(this.icon)); -}, -selectedChanged: function() { -this.addRemoveClass("enyo-selected", this.selected); -}, -rendered: function() { -this.inherited(arguments), this.expandable && !this.expanded && this.quickCollapse(); -}, -addNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent(n); -this.$.client.render(); -}, -addTextNodes: function(e) { -this.destroyClientControls(); -for (var t = 0, n; n = e[t]; t++) this.createComponent({ -content: n -}); -this.$.client.render(); -}, -tap: function(e, t) { -return this.onlyIconExpands ? t.target == this.$.icon.hasNode() ? this.toggleExpanded() : this.doNodeTap() : (this.toggleExpanded(), this.doNodeTap()), !0; -}, -dblclick: function(e, t) { -return this.doNodeDblClick(), !0; -}, -toggleExpanded: function() { -this.setExpanded(!this.expanded); -}, -quickCollapse: function() { -this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "0"); -var e = this.$.client.getBounds().height; -this.$.client.setBounds({ -top: -e -}); -}, -_expand: function() { -this.addClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), this.$.client.setBounds({ -top: 0 -}), setTimeout(enyo.bind(this, function() { -this.expanded && (this.removeClass("enyo-animate"), this.$.box.applyStyle("height", "auto")); -}), 225); -}, -_collapse: function() { -this.removeClass("enyo-animate"); -var e = this.$.client.getBounds().height; -this.$.box.setBounds({ -height: e -}), setTimeout(enyo.bind(this, function() { -this.addClass("enyo-animate"), this.$.box.applyStyle("height", "0"), this.$.client.setBounds({ -top: -e -}); -}), 25); -}, -expandedChanged: function(e) { -if (!this.expandable) this.expanded = !1; else { -var t = { -expanded: this.expanded -}; -this.doExpand(t), t.wait || this.effectExpanded(); -} -}, -effectExpanded: function() { -this.$.client && (this.expanded ? this._expand() : this._collapse()); -} -}); - -// ImageViewPin.js - -enyo.kind({ -name: "enyo.ImageViewPin", -kind: "enyo.Control", -published: { -highlightAnchorPoint: !1, -anchor: { -top: 0, -left: 0 -}, -position: { -top: 0, -left: 0 -} -}, -style: "position:absolute;z-index:1000;width:0px;height:0px;", -handlers: { -onPositionPin: "reAnchor" -}, -create: function() { -this.inherited(arguments), this.styleClientControls(), this.positionClientControls(), this.highlightAnchorPointChanged(), this.anchorChanged(); -}, -styleClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) e[t].applyStyle("position", "absolute"); -}, -positionClientControls: function() { -var e = this.getClientControls(); -for (var t = 0; t < e.length; t++) for (var n in this.position) e[t].applyStyle(n, this.position[n] + "px"); -}, -highlightAnchorPointChanged: function() { -this.addRemoveClass("pinDebug", this.highlightAnchorPoint); -}, -anchorChanged: function() { -var e = null, t = null; -for (t in this.anchor) { -e = this.anchor[t].toString().match(/^(\d+(?:\.\d+)?)(.*)$/); -if (!e) continue; -this.anchor[t + "Coords"] = { -value: e[1], -units: e[2] || "px" -}; -} -}, -reAnchor: function(e, t) { -var n = t.scale, r = t.bounds, i = this.anchor.right ? this.anchor.rightCoords.units == "px" ? r.width + r.x - this.anchor.rightCoords.value * n : r.width * (100 - this.anchor.rightCoords.value) / 100 + r.x : this.anchor.leftCoords.units == "px" ? this.anchor.leftCoords.value * n + r.x : r.width * this.anchor.leftCoords.value / 100 + r.x, s = this.anchor.bottom ? this.anchor.bottomCoords.units == "px" ? r.height + r.y - this.anchor.bottomCoords.value * n : r.height * (100 - this.anchor.bottomCoords.value) / 100 + r.y : this.anchor.topCoords.units == "px" ? this.anchor.topCoords.value * n + r.y : r.height * this.anchor.topCoords.value / 100 + r.y; -this.applyStyle("left", i + "px"), this.applyStyle("top", s + "px"); -} -}); - -// ImageView.js - -enyo.kind({ -name: "enyo.ImageView", -kind: enyo.Scroller, -touchOverscroll: !1, -thumb: !1, -animate: !0, -verticalDragPropagation: !0, -horizontalDragPropagation: !0, -published: { -scale: "auto", -disableZoom: !1, -src: undefined -}, -events: { -onZoom: "" -}, -touch: !0, -preventDragPropagation: !1, -handlers: { -ondragstart: "dragPropagation" -}, -components: [ { -name: "animator", -kind: "Animator", -onStep: "zoomAnimationStep", -onEnd: "zoomAnimationEnd" -}, { -name: "viewport", -style: "overflow:hidden;min-height:100%;min-width:100%;", -classes: "enyo-fit", -ongesturechange: "gestureTransform", -ongestureend: "saveState", -ontap: "singleTap", -ondblclick: "doubleClick", -onmousewheel: "mousewheel", -components: [ { -kind: "Image", -ondown: "down" -} ] -} ], -create: function() { -this.inherited(arguments), this.canTransform = enyo.dom.canTransform(), this.canTransform || this.$.image.applyStyle("position", "relative"), this.canAccelerate = enyo.dom.canAccelerate(), this.bufferImage = new Image, this.bufferImage.onload = enyo.bind(this, "imageLoaded"), this.bufferImage.onerror = enyo.bind(this, "imageError"), this.srcChanged(), this.getStrategy().setDragDuringGesture(!1), this.getStrategy().$.scrollMath && this.getStrategy().$.scrollMath.start(); -}, -down: function(e, t) { -t.preventDefault(); -}, -dragPropagation: function(e, t) { -var n = this.getStrategy().getScrollBounds(), r = n.top === 0 && t.dy > 0 || n.top >= n.maxTop - 2 && t.dy < 0, i = n.left === 0 && t.dx > 0 || n.left >= n.maxLeft - 2 && t.dx < 0; -return !(r && this.verticalDragPropagation || i && this.horizontalDragPropagation); -}, -mousewheel: function(e, t) { -t.pageX |= t.clientX + t.target.scrollLeft, t.pageY |= t.clientY + t.target.scrollTop; -var n = (this.maxScale - this.minScale) / 10, r = this.scale; -if (t.wheelDelta > 0 || t.detail < 0) this.scale = this.limitScale(this.scale + n); else if (t.wheelDelta < 0 || t.detail > 0) this.scale = this.limitScale(this.scale - n); -return this.eventPt = this.calcEventLocation(t), this.transformImage(this.scale), r != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null, t.preventDefault(), !0; -}, -srcChanged: function() { -this.src && this.src.length > 0 && this.bufferImage && this.src != this.bufferImage.src && (this.bufferImage.src = this.src); -}, -imageLoaded: function(e) { -this.originalWidth = this.bufferImage.width, this.originalHeight = this.bufferImage.height, this.scaleChanged(), this.$.image.setSrc(this.bufferImage.src), enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"), this.positionClientControls(this.scale), this.alignImage(); -}, -resizeHandler: function() { -this.inherited(arguments), this.$.image.src && this.scaleChanged(); -}, -scaleChanged: function() { -var e = this.hasNode(); -if (e) { -this.containerWidth = e.clientWidth, this.containerHeight = e.clientHeight; -var t = this.containerWidth / this.originalWidth, n = this.containerHeight / this.originalHeight; -this.minScale = Math.min(t, n), this.maxScale = this.minScale * 3 < 1 ? 1 : this.minScale * 3, this.scale == "auto" ? this.scale = this.minScale : this.scale == "width" ? this.scale = t : this.scale == "height" ? this.scale = n : this.scale == "fit" ? (this.fitAlignment = "center", this.scale = Math.max(t, n)) : (this.maxScale = Math.max(this.maxScale, this.scale), this.scale = this.limitScale(this.scale)); -} -this.eventPt = this.calcEventLocation(), this.transformImage(this.scale); -}, -imageError: function(e) { -enyo.error("Error loading image: " + this.src), this.bubble("onerror", e); -}, -alignImage: function() { -if (this.fitAlignment && this.fitAlignment === "center") { -var e = this.getScrollBounds(); -this.setScrollLeft(e.maxLeft / 2), this.setScrollTop(e.maxTop / 2); -} -}, -gestureTransform: function(e, t) { -this.eventPt = this.calcEventLocation(t), this.transformImage(this.limitScale(this.scale * t.scale)); -}, -calcEventLocation: function(e) { -var t = { -x: 0, -y: 0 -}; -if (e && this.hasNode()) { -var n = this.node.getBoundingClientRect(); -t.x = Math.round(e.pageX - n.left - this.imageBounds.x), t.x = Math.max(0, Math.min(this.imageBounds.width, t.x)), t.y = Math.round(e.pageY - n.top - this.imageBounds.y), t.y = Math.max(0, Math.min(this.imageBounds.height, t.y)); -} -return t; -}, -transformImage: function(e) { -this.tapped = !1; -var t = this.imageBounds || this.innerImageBounds(e); -this.imageBounds = this.innerImageBounds(e), this.scale > this.minScale ? this.$.viewport.applyStyle("cursor", "move") : this.$.viewport.applyStyle("cursor", null), this.$.viewport.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px" -}), this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / t.width, this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / t.height; -var n, r; -this.$.animator.ratioLock ? (n = this.$.animator.ratioLock.x * this.imageBounds.width - this.containerWidth / 2, r = this.$.animator.ratioLock.y * this.imageBounds.height - this.containerHeight / 2) : (n = this.ratioX * this.imageBounds.width - this.eventPt.x, r = this.ratioY * this.imageBounds.height - this.eventPt.y), n = Math.max(0, Math.min(this.imageBounds.width - this.containerWidth, n)), r = Math.max(0, Math.min(this.imageBounds.height - this.containerHeight, r)); -if (this.canTransform) { -var i = { -scale: e -}; -this.canAccelerate ? i = enyo.mixin({ -translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px" -}, i) : i = enyo.mixin({ -translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px" -}, i), enyo.dom.transform(this.$.image, i); -} else this.$.image.setBounds({ -width: this.imageBounds.width + "px", -height: this.imageBounds.height + "px", -left: this.imageBounds.left + "px", -top: this.imageBounds.top + "px" -}); -this.setScrollLeft(n), this.setScrollTop(r), this.positionClientControls(e); -}, -limitScale: function(e) { -return this.disableZoom ? e = this.scale : e > this.maxScale ? e = this.maxScale : e < this.minScale && (e = this.minScale), e; -}, -innerImageBounds: function(e) { -var t = this.originalWidth * e, n = this.originalHeight * e, r = { -x: 0, -y: 0, -transX: 0, -transY: 0 -}; -return t < this.containerWidth && (r.x += (this.containerWidth - t) / 2), n < this.containerHeight && (r.y += (this.containerHeight - n) / 2), this.canTransform && (r.transX -= (this.originalWidth - t) / 2, r.transY -= (this.originalHeight - n) / 2), { -left: r.x + r.transX, -top: r.y + r.transY, -width: t, -height: n, -x: r.x, -y: r.y -}; -}, -saveState: function(e, t) { -var n = this.scale; -this.scale *= t.scale, this.scale = this.limitScale(this.scale), n != this.scale && this.doZoom({ -scale: this.scale -}), this.ratioX = this.ratioY = null; -}, -doubleClick: function(e, t) { -enyo.platform.ie == 8 && (this.tapped = !0, t.pageX = t.clientX + t.target.scrollLeft, t.pageY = t.clientY + t.target.scrollTop, this.singleTap(e, t), t.preventDefault()); -}, -singleTap: function(e, t) { -setTimeout(enyo.bind(this, function() { -this.tapped = !1; -}), 300), this.tapped ? (this.tapped = !1, this.smartZoom(e, t)) : this.tapped = !0; -}, -smartZoom: function(e, t) { -var n = this.hasNode(), r = this.$.image.hasNode(); -if (n && r && this.hasNode() && !this.disableZoom) { -var i = this.scale; -this.scale != this.minScale ? this.scale = this.minScale : this.scale = this.maxScale, this.eventPt = this.calcEventLocation(t); -if (this.animate) { -var s = { -x: (this.eventPt.x + this.getScrollLeft()) / this.imageBounds.width, -y: (this.eventPt.y + this.getScrollTop()) / this.imageBounds.height -}; -this.$.animator.play({ -duration: 350, -ratioLock: s, -baseScale: i, -deltaScale: this.scale - i -}); -} else this.transformImage(this.scale), this.doZoom({ -scale: this.scale -}); -} -}, -zoomAnimationStep: function(e, t) { -var n = this.$.animator.baseScale + this.$.animator.deltaScale * this.$.animator.value; -this.transformImage(n); -}, -zoomAnimationEnd: function(e, t) { -this.doZoom({ -scale: this.scale -}), this.$.animator.ratioLock = undefined; -}, -positionClientControls: function(e) { -this.waterfallDown("onPositionPin", { -scale: e, -bounds: this.imageBounds -}); -} -}); - -// ImageCarousel.js - -enyo.kind({ -name: "enyo.ImageCarousel", -kind: enyo.Panels, -arrangerKind: "enyo.CarouselArranger", -defaultScale: "auto", -disableZoom: !1, -lowMemory: !1, -published: { -images: [] -}, -handlers: { -onTransitionStart: "transitionStart", -onTransitionFinish: "transitionFinish" -}, -create: function() { -this.inherited(arguments), this.imageCount = this.images.length, this.images.length > 0 && (this.initContainers(), this.loadNearby()); -}, -initContainers: function() { -for (var e = 0; e < this.images.length; e++) this.$["container" + e] || (this.createComponent({ -name: "container" + e, -style: "height:100%; width:100%;" -}), this.$["container" + e].render()); -for (e = this.images.length; e < this.imageCount; e++) this.$["image" + e] && this.$["image" + e].destroy(), this.$["container" + e].destroy(); -this.imageCount = this.images.length; -}, -loadNearby: function() { -var e = this.getBufferRange(); -for (var t in e) this.loadImageView(e[t]); -}, -getBufferRange: function() { -var e = []; -if (this.layout.containerBounds) { -var t = 1, n = this.layout.containerBounds, r, i, s, o, u, a; -o = this.index - 1, u = 0, a = n.width * t; -while (o >= 0 && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.unshift(o), o--; -o = this.index, u = 0, a = n.width * (t + 1); -while (o < this.images.length && u <= a) s = this.$["container" + o], u += s.width + s.marginWidth, e.push(o), o++; -} -return e; -}, -reflow: function() { -this.inherited(arguments), this.loadNearby(); -}, -loadImageView: function(e) { -return this.wrap && (e = (e % this.images.length + this.images.length) % this.images.length), e >= 0 && e <= this.images.length - 1 && (this.$["image" + e] ? this.$["image" + e].src != this.images[e] && (this.$["image" + e].setSrc(this.images[e]), this.$["image" + e].setScale(this.defaultScale), this.$["image" + e].setDisableZoom(this.disableZoom)) : (this.$["container" + e].createComponent({ -name: "image" + e, -kind: "ImageView", -scale: this.defaultScale, -disableZoom: this.disableZoom, -src: this.images[e], -verticalDragPropagation: !1, -style: "height:100%; width:100%;" -}, { -owner: this -}), this.$["image" + e].render())), this.$["image" + e]; -}, -setImages: function(e) { -this.setPropertyValue("images", e, "imagesChanged"); -}, -imagesChanged: function() { -this.initContainers(), this.loadNearby(); -}, -indexChanged: function() { -this.loadNearby(), this.lowMemory && this.cleanupMemory(), this.inherited(arguments); -}, -transitionStart: function(e, t) { -if (t.fromIndex == t.toIndex) return !0; -}, -transitionFinish: function(e, t) { -this.loadNearby(), this.lowMemory && this.cleanupMemory(); -}, -getActiveImage: function() { -return this.getImageByIndex(this.index); -}, -getImageByIndex: function(e) { -return this.$["image" + e] || this.loadImageView(e); -}, -cleanupMemory: function() { -var e = getBufferRange(); -for (var t = 0; t < this.images.length; t++) enyo.indexOf(t, e) === -1 && this.$["image" + t] && this.$["image" + t].destroy(); -} -}); - -// Icon.js - -enyo.kind({ -name: "onyx.Icon", -published: { -src: "", -disabled: !1 -}, -classes: "onyx-icon", -create: function() { -this.inherited(arguments), this.src && this.srcChanged(), this.disabledChanged(); -}, -disabledChanged: function() { -this.addRemoveClass("disabled", this.disabled); -}, -srcChanged: function() { -this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); -} -}); - -// Button.js - -enyo.kind({ -name: "onyx.Button", -kind: "enyo.Button", -classes: "onyx-button enyo-unselectable", -create: function() { -enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -} -}); - -// IconButton.js - -enyo.kind({ -name: "onyx.IconButton", -kind: "onyx.Icon", -published: { -active: !1 -}, -classes: "onyx-icon-button", -create: function() { -enyo.platform.firefoxOS && (this.handlers.ondown = "down", this.handlers.onleave = "leave"), this.inherited(arguments); -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -}, -rendered: function() { -this.inherited(arguments), this.activeChanged(); -}, -tap: function() { -if (this.disabled) return !0; -this.setActive(!0); -}, -activeChanged: function() { -this.bubble("onActivate"); -} -}); - -// Checkbox.js - -enyo.kind({ -name: "onyx.Checkbox", -classes: "onyx-checkbox", -kind: enyo.Checkbox, -tag: "div", -handlers: { -onclick: "" -}, -tap: function(e, t) { -return this.disabled || (this.setChecked(!this.getChecked()), this.bubble("onchange")), !this.disabled; -}, -dragstart: function() {} -}); - -// Drawer.js - -enyo.kind({ -name: "onyx.Drawer", -published: { -open: !0, -orient: "v", -animated: !0 -}, -style: "overflow: hidden; position: relative;", -tools: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorEnd" -}, { -name: "client", -style: "position: relative;", -classes: "enyo-border-box" -} ], -create: function() { -this.inherited(arguments), this.animatedChanged(), this.openChanged(); -}, -initComponents: function() { -this.createChrome(this.tools), this.inherited(arguments); -}, -animatedChanged: function() { -!this.animated && this.hasNode() && this.$.animator.isAnimating() && (this.$.animator.stop(), this.animatorEnd()); -}, -openChanged: function() { -this.$.client.show(); -if (this.hasNode()) if (this.$.animator.isAnimating()) this.$.animator.reverse(); else { -var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left"; -this.applyStyle(t, null); -var r = this.hasNode()[e ? "scrollHeight" : "scrollWidth"]; -this.animated ? this.$.animator.play({ -startValue: this.open ? 0 : r, -endValue: this.open ? r : 0, -dimension: t, -position: n -}) : this.animatorEnd(); -} else this.$.client.setShowing(this.open); -}, -animatorStep: function(e) { -if (this.hasNode()) { -var t = e.dimension; -this.node.style[t] = this.domStyles[t] = e.value + "px"; -} -var n = this.$.client.hasNode(); -if (n) { -var r = e.position, i = this.open ? e.endValue : e.startValue; -n.style[r] = this.$.client.domStyles[r] = e.value - i + "px"; -} -this.container && this.container.resized(); -}, -animatorEnd: function() { -if (!this.open) this.$.client.hide(); else { -this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); -var e = this.orient == "v", t = e ? "height" : "width", n = e ? "top" : "left", r = this.$.client.hasNode(); -r && (r.style[n] = this.$.client.domStyles[n] = null), this.node && (this.node.style[t] = this.domStyles[t] = null); -} -this.container && this.container.resized(); -} -}); - -// Grabber.js - -enyo.kind({ -name: "onyx.Grabber", -classes: "onyx-grabber" -}); - -// Groupbox.js - -enyo.kind({ -name: "onyx.Groupbox", -classes: "onyx-groupbox" -}), enyo.kind({ -name: "onyx.GroupboxHeader", -classes: "onyx-groupbox-header" -}); - -// Input.js - -enyo.kind({ -name: "onyx.Input", -kind: "enyo.Input", -classes: "onyx-input" -}); - -// Popup.js - -enyo.kind({ -name: "onyx.Popup", -kind: "Popup", -classes: "onyx-popup", -published: { -scrimWhenModal: !0, -scrim: !1, -scrimClassName: "" -}, -statics: { -count: 0 -}, -defaultZ: 120, -showingChanged: function() { -this.showing ? (onyx.Popup.count++, this.applyZIndex()) : onyx.Popup.count > 0 && onyx.Popup.count--, this.showHideScrim(this.showing), this.inherited(arguments); -}, -showHideScrim: function(e) { -if (this.floating && (this.scrim || this.modal && this.scrimWhenModal)) { -var t = this.getScrim(); -if (e) { -var n = this.getScrimZIndex(); -this._scrimZ = n, t.showAtZIndex(n); -} else t.hideAtZIndex(this._scrimZ); -enyo.call(t, "addRemoveClass", [ this.scrimClassName, t.showing ]); -} -}, -getScrimZIndex: function() { -return this.findZIndex() - 1; -}, -getScrim: function() { -return this.modal && this.scrimWhenModal && !this.scrim ? onyx.scrimTransparent.make() : onyx.scrim.make(); -}, -applyZIndex: function() { -this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1, this.applyStyle("z-index", this._zIndex); -}, -findZIndex: function() { -var e = this.defaultZ; -return this._zIndex ? e = this._zIndex : this.hasNode() && (e = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || e), this._zIndex = e; -} -}); - -// TextArea.js - -enyo.kind({ -name: "onyx.TextArea", -kind: "enyo.TextArea", -classes: "onyx-textarea" -}); - -// RichText.js - -enyo.kind({ -name: "onyx.RichText", -kind: "enyo.RichText", -classes: "onyx-richtext" -}); - -// InputDecorator.js - -enyo.kind({ -name: "onyx.InputDecorator", -kind: "enyo.ToolDecorator", -tag: "label", -classes: "onyx-input-decorator", -published: { -alwaysLooksFocused: !1 -}, -handlers: { -onDisabledChange: "disabledChange", -onfocus: "receiveFocus", -onblur: "receiveBlur" -}, -create: function() { -this.inherited(arguments), this.updateFocus(!1); -}, -alwaysLooksFocusedChanged: function(e) { -this.updateFocus(this.focus); -}, -updateFocus: function(e) { -this.focused = e, this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); -}, -receiveFocus: function() { -this.updateFocus(!0); -}, -receiveBlur: function() { -this.updateFocus(!1); -}, -disabledChange: function(e, t) { -this.addRemoveClass("onyx-disabled", t.originator.disabled); -} -}); - -// Tooltip.js - -enyo.kind({ -name: "onyx.Tooltip", -kind: "onyx.Popup", -classes: "onyx-tooltip below left-arrow", -autoDismiss: !1, -showDelay: 500, -defaultLeft: -6, -handlers: { -onRequestShowTooltip: "requestShow", -onRequestHideTooltip: "requestHide" -}, -requestShow: function() { -return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; -}, -cancelShow: function() { -clearTimeout(this.showJob); -}, -requestHide: function() { -return this.cancelShow(), this.inherited(arguments); -}, -showingChanged: function() { -this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -adjustPosition: function(e) { -if (this.showing && this.hasNode()) { -var t = this.node.getBoundingClientRect(); -t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ -"margin-left": -t.width, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); -} -}, -resizeHandler: function() { -this.applyPosition({ -"margin-left": this.defaultLeft, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); -} -}); - -// TooltipDecorator.js - -enyo.kind({ -name: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator", -handlers: { -onenter: "enter", -onleave: "leave" -}, -enter: function() { -this.requestShowTooltip(); -}, -leave: function() { -this.requestHideTooltip(); -}, -tap: function() { -this.requestHideTooltip(); -}, -requestShowTooltip: function() { -this.waterfallDown("onRequestShowTooltip"); -}, -requestHideTooltip: function() { -this.waterfallDown("onRequestHideTooltip"); -} -}); - -// MenuDecorator.js - -enyo.kind({ -name: "onyx.MenuDecorator", -kind: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator enyo-unselectable", -handlers: { -onActivate: "activated", -onHide: "menuHidden" -}, -activated: function(e, t) { -this.requestHideTooltip(), t.originator.active && (this.menuActive = !0, this.activator = t.originator, this.activator.addClass("active"), this.requestShowMenu()); -}, -requestShowMenu: function() { -this.waterfallDown("onRequestShowMenu", { -activator: this.activator -}); -}, -requestHideMenu: function() { -this.waterfallDown("onRequestHideMenu"); -}, -menuHidden: function() { -this.menuActive = !1, this.activator && (this.activator.setActive(!1), this.activator.removeClass("active")); -}, -enter: function(e) { -this.menuActive || this.inherited(arguments); -}, -leave: function(e, t) { -this.menuActive || this.inherited(arguments); -} -}); - -// Menu.js - -enyo.kind({ -name: "onyx.Menu", -kind: "onyx.Popup", -modal: !0, -defaultKind: "onyx.MenuItem", -classes: "onyx-menu", -published: { -maxHeight: 200, -scrolling: !0 -}, -handlers: { -onActivate: "itemActivated", -onRequestShowMenu: "requestMenuShow", -onRequestHideMenu: "requestHide" -}, -childComponents: [ { -name: "client", -kind: "enyo.Scroller", -strategyKind: "TouchScrollStrategy" -} ], -showOnTop: !1, -scrollerName: "client", -create: function() { -this.inherited(arguments), this.maxHeightChanged(); -}, -initComponents: function() { -this.scrolling && this.createComponents(this.childComponents, { -isChrome: !0 -}), this.inherited(arguments); -}, -getScroller: function() { -return this.$[this.scrollerName]; -}, -maxHeightChanged: function() { -this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); -}, -itemActivated: function(e, t) { -return t.originator.setActive(!1), !0; -}, -showingChanged: function() { -this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(!0); -}, -requestMenuShow: function(e, t) { -if (this.floating) { -var n = t.activator.hasNode(); -if (n) { -var r = this.activatorOffset = this.getPageOffset(n); -this.applyPosition({ -top: r.top + (this.showOnTop ? 0 : r.height), -left: r.left, -width: r.width -}); -} -} -return this.show(), !0; -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -getPageOffset: function(e) { -var t = e.getBoundingClientRect(), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; -return { -top: t.top + n, -left: t.left + r, -height: i, -width: s -}; -}, -adjustPosition: function() { -if (this.showing && this.hasNode()) { -this.scrolling && !this.showOnTop && this.getScroller().setMaxHeight(this.maxHeight + "px"), this.removeClass("onyx-menu-up"), this.floating || this.applyPosition({ -left: "auto" -}); -var e = this.node.getBoundingClientRect(), t = e.height === undefined ? e.bottom - e.top : e.height, n = window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight, r = window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; -this.menuUp = e.top + t > n && n - e.bottom < e.top - t, this.addRemoveClass("onyx-menu-up", this.menuUp); -if (this.floating) { -var i = this.activatorOffset; -this.menuUp ? this.applyPosition({ -top: i.top - t + (this.showOnTop ? i.height : 0), -bottom: "auto" -}) : e.top < i.top && i.top + (this.showOnTop ? 0 : i.height) + t < n && this.applyPosition({ -top: i.top + (this.showOnTop ? 0 : i.height), -bottom: "auto" -}); -} -e.right > r && (this.floating ? this.applyPosition({ -left: r - e.width -}) : this.applyPosition({ -left: -(e.right - r) -})), e.left < 0 && (this.floating ? this.applyPosition({ -left: 0, -right: "auto" -}) : this.getComputedStyleValue("right") == "auto" ? this.applyPosition({ -left: -e.left -}) : this.applyPosition({ -right: e.left -})); -if (this.scrolling && !this.showOnTop) { -e = this.node.getBoundingClientRect(); -var s; -this.menuUp ? s = this.maxHeight < e.bottom ? this.maxHeight : e.bottom : s = e.top + this.maxHeight < n ? this.maxHeight : n - e.top, this.getScroller().setMaxHeight(s + "px"); -} -} -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -}, -requestHide: function() { -this.setShowing(!1); -} -}); - -// MenuItem.js - -enyo.kind({ -name: "onyx.MenuItem", -kind: "enyo.Button", -events: { -onSelect: "", -onItemContentChange: "" -}, -classes: "onyx-menu-item", -tag: "div", -create: function() { -this.inherited(arguments), this.active && this.bubble("onActivate"); -}, -tap: function(e) { -this.inherited(arguments), this.bubble("onRequestHideMenu"), this.doSelect({ -selected: this, -content: this.content -}); -}, -contentChanged: function(e) { -this.inherited(arguments), this.doItemContentChange({ -content: this.content -}); -} -}); - -// PickerDecorator.js - -enyo.kind({ -name: "onyx.PickerDecorator", -kind: "onyx.MenuDecorator", -classes: "onyx-picker-decorator", -defaultKind: "onyx.PickerButton", -handlers: { -onChange: "change" -}, -change: function(e, t) { -this.waterfallDown("onChange", t); -} -}); - -// PickerButton.js - -enyo.kind({ -name: "onyx.PickerButton", -kind: "onyx.Button", -handlers: { -onChange: "change" -}, -change: function(e, t) { -t.content !== undefined && this.setContent(t.content); -} -}); - -// Picker.js - -enyo.kind({ -name: "onyx.Picker", -kind: "onyx.Menu", -classes: "onyx-picker enyo-unselectable", -published: { -selected: null -}, -events: { -onChange: "" -}, -handlers: { -onItemContentChange: "itemContentChange" -}, -floating: !0, -showOnTop: !0, -initComponents: function() { -this.setScrolling(!0), this.inherited(arguments); -}, -showingChanged: function() { -this.getScroller().setShowing(this.showing), this.inherited(arguments), this.showing && this.selected && this.scrollToSelected(); -}, -scrollToSelected: function() { -this.getScroller().scrollToControl(this.selected, !this.menuUp); -}, -itemActivated: function(e, t) { -return this.processActivatedItem(t.originator), this.inherited(arguments); -}, -processActivatedItem: function(e) { -e.active && this.setSelected(e); -}, -selectedChanged: function(e) { -e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ -selected: this.selected, -content: this.selected.content -})); -}, -itemContentChange: function(e, t) { -t.originator == this.selected && this.doChange({ -selected: this.selected, -content: this.selected.content -}); -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -} -}); - -// FlyweightPicker.js - -enyo.kind({ -name: "onyx.FlyweightPicker", -kind: "onyx.Picker", -classes: "onyx-flyweight-picker", -published: { -count: 0 -}, -events: { -onSetupItem: "", -onSelect: "" -}, -handlers: { -onSelect: "itemSelect" -}, -components: [ { -name: "scroller", -kind: "enyo.Scroller", -strategyKind: "TouchScrollStrategy", -components: [ { -name: "flyweight", -kind: "FlyweightRepeater", -noSelect: !0, -ontap: "itemTap" -} ] -} ], -scrollerName: "scroller", -initComponents: function() { -this.controlParentName = "flyweight", this.inherited(arguments), this.$.flyweight.$.client.children[0].setActive(!0); -}, -create: function() { -this.inherited(arguments), this.countChanged(); -}, -rendered: function() { -this.inherited(arguments), this.selectedChanged(); -}, -scrollToSelected: function() { -var e = this.$.flyweight.fetchRowNode(this.selected); -this.getScroller().scrollToNode(e, !this.menuUp); -}, -countChanged: function() { -this.$.flyweight.count = this.count; -}, -processActivatedItem: function(e) { -this.item = e; -}, -selectedChanged: function(e) { -if (!this.item) return; -e != null && (this.item.removeClass("selected"), this.$.flyweight.renderRow(e)); -var t; -this.selected != null && (this.item.addClass("selected"), this.$.flyweight.renderRow(this.selected), this.item.removeClass("selected"), t = this.$.flyweight.fetchRowNode(this.selected)), this.doChange({ -selected: this.selected, -content: t && t.textContent || this.item.content -}); -}, -itemTap: function(e, t) { -this.setSelected(t.rowIndex), this.doSelect({ -selected: this.item, -content: this.item.content -}); -}, -itemSelect: function(e, t) { -if (t.originator != this) return !0; -} -}); - -// DatePicker.js - -enyo.kind({ -name: "onyx.DatePicker", -classes: "onyx-toolbar-inline", -published: { -disabled: !1, -locale: "en_us", -dayHidden: !1, -monthHidden: !1, -yearHidden: !1, -minYear: 1900, -maxYear: 2099, -value: null -}, -events: { -onSelect: "" -}, -create: function() { -this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); -}, -initDefaults: function() { -var e = [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; -enyo.g11n && (this._tf = new enyo.g11n.Fmts({ -locale: this.locale -}), e = this._tf.getMonthFields()), this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : "mdy"), this.dayHiddenChanged(), this.monthHiddenChanged(), this.yearHiddenChanged(); -var t = this.value = this.value || new Date; -for (var n = 0, r; r = e[n]; n++) this.$.monthPicker.createComponent({ -content: r, -value: n, -active: n == t.getMonth() -}); -var i = t.getFullYear(); -this.$.yearPicker.setSelected(i - this.minYear); -for (n = 1; n <= this.monthLength(t.getYear(), t.getMonth()); n++) this.$.dayPicker.createComponent({ -content: n, -value: n, -active: n == t.getDate() -}); -}, -monthLength: function(e, t) { -return 32 - (new Date(e, t, 32)).getDate(); -}, -setupYear: function(e, t) { -this.$.year.setContent(this.minYear + t.index); -}, -setupPickers: function(e) { -var t = e.split(""), n, r, i; -for (r = 0, i = t.length; r < i; r++) { -n = t[r]; -switch (n) { -case "d": -this.createDay(); -break; -case "m": -this.createMonth(); -break; -case "y": -this.createYear(); -break; -default: -} -} -}, -createYear: function() { -var e = this.maxYear - this.minYear; -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateYear", -components: [ { -classes: "onyx-datepicker-year", -name: "yearPickerButton", -disabled: this.disabled -}, { -name: "yearPicker", -kind: "onyx.FlyweightPicker", -count: ++e, -onSetupItem: "setupYear", -components: [ { -name: "year" -} ] -} ] -}); -}, -createMonth: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateMonth", -components: [ { -classes: "onyx-datepicker-month", -name: "monthPickerButton", -disabled: this.disabled -}, { -name: "monthPicker", -kind: "onyx.Picker" -} ] -}); -}, -createDay: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateDay", -components: [ { -classes: "onyx-datepicker-day", -name: "dayPickerButton", -disabled: this.disabled -}, { -name: "dayPicker", -kind: "onyx.Picker" -} ] -}); -}, -localeChanged: function() { -this.refresh(); -}, -dayHiddenChanged: function() { -this.$.dayPicker.getParent().setShowing(this.dayHidden ? !1 : !0); -}, -monthHiddenChanged: function() { -this.$.monthPicker.getParent().setShowing(this.monthHidden ? !1 : !0); -}, -yearHiddenChanged: function() { -this.$.yearPicker.getParent().setShowing(this.yearHidden ? !1 : !0); -}, -minYearChanged: function() { -this.refresh(); -}, -maxYearChanged: function() { -this.refresh(); -}, -valueChanged: function() { -this.refresh(); -}, -disabledChanged: function() { -this.$.yearPickerButton.setDisabled(this.disabled), this.$.monthPickerButton.setDisabled(this.disabled), this.$.dayPickerButton.setDisabled(this.disabled); -}, -updateDay: function(e, t) { -var n = this.calcDate(this.value.getFullYear(), this.value.getMonth(), t.selected.value); -return this.doSelect({ -name: this.name, -value: n -}), this.setValue(n), !0; -}, -updateMonth: function(e, t) { -var n = this.calcDate(this.value.getFullYear(), t.selected.value, this.value.getDate()); -return this.doSelect({ -name: this.name, -value: n -}), this.setValue(n), !0; -}, -updateYear: function(e, t) { -if (t.originator.selected != -1) { -var n = this.calcDate(this.minYear + t.originator.selected, this.value.getMonth(), this.value.getDate()); -this.doSelect({ -name: this.name, -value: n -}), this.setValue(n); -} -return !0; -}, -calcDate: function(e, t, n) { -return new Date(e, t, n, this.value.getHours(), this.value.getMinutes(), this.value.getSeconds(), this.value.getMilliseconds()); -}, -refresh: function() { -this.destroyClientControls(), this.initDefaults(), this.render(); -} -}); - -// TimePicker.js - -enyo.kind({ -name: "onyx.TimePicker", -classes: "onyx-toolbar-inline", -published: { -disabled: !1, -locale: "en_us", -is24HrMode: null, -value: null -}, -events: { -onSelect: "" -}, -create: function() { -this.inherited(arguments), enyo.g11n && (this.locale = enyo.g11n.currentLocale().getLocale()), this.initDefaults(); -}, -initDefaults: function() { -var e = "AM", t = "PM"; -this.is24HrMode == null && (this.is24HrMode = !1), enyo.g11n && (this._tf = new enyo.g11n.Fmts({ -locale: this.locale -}), e = this._tf.getAmCaption(), t = this._tf.getPmCaption(), this.is24HrMode == null && (this.is24HrMode = !this._tf.isAmPm())), this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : "hma"); -var n = this.value = this.value || new Date, r; -if (!this.is24HrMode) { -var i = n.getHours(); -i = i === 0 ? 12 : i; -for (r = 1; r <= 12; r++) this.$.hourPicker.createComponent({ -content: r, -value: r, -active: r == (i > 12 ? i % 12 : i) -}); -} else for (r = 0; r < 24; r++) this.$.hourPicker.createComponent({ -content: r, -value: r, -active: r == n.getHours() -}); -for (r = 0; r <= 59; r++) this.$.minutePicker.createComponent({ -content: r < 10 ? "0" + r : r, -value: r, -active: r == n.getMinutes() -}); -n.getHours() >= 12 ? this.$.ampmPicker.createComponents([ { -content: e -}, { -content: t, -active: !0 -} ]) : this.$.ampmPicker.createComponents([ { -content: e, -active: !0 -}, { -content: t -} ]), this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); -}, -setupPickers: function(e) { -var t = e.split(""), n, r, i; -for (r = 0, i = t.length; r < i; r++) { -n = t[r]; -switch (n) { -case "h": -this.createHour(); -break; -case "m": -this.createMinute(); -break; -case "a": -this.createAmPm(); -break; -default: -} -} -}, -createHour: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateHour", -components: [ { -classes: "onyx-timepicker-hour", -name: "hourPickerButton", -disabled: this.disabled -}, { -name: "hourPicker", -kind: "onyx.Picker" -} ] -}); -}, -createMinute: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateMinute", -components: [ { -classes: "onyx-timepicker-minute", -name: "minutePickerButton", -disabled: this.disabled -}, { -name: "minutePicker", -kind: "onyx.Picker" -} ] -}); -}, -createAmPm: function() { -this.createComponent({ -kind: "onyx.PickerDecorator", -onSelect: "updateAmPm", -components: [ { -classes: "onyx-timepicker-ampm", -name: "ampmPickerButton", -disabled: this.disabled -}, { -name: "ampmPicker", -kind: "onyx.Picker" -} ] -}); -}, -disabledChanged: function() { -this.$.hourPickerButton.setDisabled(this.disabled), this.$.minutePickerButton.setDisabled(this.disabled), this.$.ampmPickerButton.setDisabled(this.disabled); -}, -localeChanged: function() { -this.is24HrMode = null, this.refresh(); -}, -is24HrModeChanged: function() { -this.refresh(); -}, -valueChanged: function() { -this.refresh(); -}, -updateHour: function(e, t) { -var n = t.selected.value; -if (!this.is24HrMode) { -var r = this.$.ampmPicker.getParent().controlAtIndex(0).content; -n = n + (n == 12 ? -12 : 0) + (this.isAm(r) ? 0 : 12); -} -return this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -updateMinute: function(e, t) { -return this.value = this.calcTime(this.value.getHours(), t.selected.value), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -updateAmPm: function(e, t) { -var n = this.value.getHours(); -return this.is24HrMode || (n += n > 11 ? this.isAm(t.content) ? -12 : 0 : this.isAm(t.content) ? 0 : 12), this.value = this.calcTime(n, this.value.getMinutes()), this.doSelect({ -name: this.name, -value: this.value -}), !0; -}, -calcTime: function(e, t) { -return new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), e, t, this.value.getSeconds(), this.value.getMilliseconds()); -}, -isAm: function(e) { -var t, n, r; -try { -t = this._tf.getAmCaption(), n = this._tf.getPmCaption(); -} catch (i) { -t = "AM", n = "PM"; -} -return e == t ? !0 : !1; -}, -refresh: function() { -this.destroyClientControls(), this.initDefaults(), this.render(); -} -}); - -// RadioButton.js - -enyo.kind({ -name: "onyx.RadioButton", -kind: "Button", -classes: "onyx-radiobutton" -}); - -// RadioGroup.js - -enyo.kind({ -name: "onyx.RadioGroup", -kind: "Group", -defaultKind: "onyx.RadioButton", -highlander: !0 -}); - -// ToggleButton.js - -enyo.kind({ -name: "onyx.ToggleButton", -classes: "onyx-toggle-button", -published: { -active: !1, -value: !1, -onContent: "On", -offContent: "Off", -disabled: !1 -}, -events: { -onChange: "" -}, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -components: [ { -name: "contentOn", -classes: "onyx-toggle-content on" -}, { -name: "contentOff", -classes: "onyx-toggle-content off" -}, { -classes: "onyx-toggle-button-knob" -} ], -create: function() { -this.inherited(arguments), this.value = Boolean(this.value || this.active), this.onContentChanged(), this.offContentChanged(), this.disabledChanged(); -}, -rendered: function() { -this.inherited(arguments), this.updateVisualState(); -}, -updateVisualState: function() { -this.addRemoveClass("off", !this.value), this.$.contentOn.setShowing(this.value), this.$.contentOff.setShowing(!this.value), this.setActive(this.value); -}, -valueChanged: function() { -this.updateVisualState(), this.doChange({ -value: this.value -}); -}, -activeChanged: function() { -this.setValue(this.active), this.bubble("onActivate"); -}, -onContentChanged: function() { -this.$.contentOn.setContent(this.onContent || ""), this.$.contentOn.addRemoveClass("empty", !this.onContent); -}, -offContentChanged: function() { -this.$.contentOff.setContent(this.offContent || ""), this.$.contentOff.addRemoveClass("empty", !this.onContent); -}, -disabledChanged: function() { -this.addRemoveClass("disabled", this.disabled); -}, -updateValue: function(e) { -this.disabled || this.setValue(e); -}, -tap: function() { -this.updateValue(!this.value); -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, this.dragged = !1, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = t.dx; -return Math.abs(n) > 10 && (this.updateValue(n > 0), this.dragged = !0), !0; -} -}, -dragfinish: function(e, t) { -this.dragging = !1, this.dragged && t.preventTap(); -} -}); - -// ToggleIconButton.js - -enyo.kind({ -name: "onyx.ToggleIconButton", -kind: "onyx.Icon", -published: { -active: !1, -value: !1 -}, -events: { -onChange: "" -}, -classes: "onyx-icon-button onyx-icon-toggle", -activeChanged: function() { -this.addRemoveClass("active", this.value), this.bubble("onActivate"); -}, -updateValue: function(e) { -this.disabled || (this.setValue(e), this.doChange({ -value: this.value -})); -}, -tap: function() { -this.updateValue(!this.value); -}, -valueChanged: function() { -this.setActive(this.value); -}, -create: function() { -this.inherited(arguments), this.value = Boolean(this.value || this.active); -}, -rendered: function() { -this.inherited(arguments), this.valueChanged(), this.removeClass("onyx-icon"); -} -}); - -// Toolbar.js - -enyo.kind({ -name: "onyx.Toolbar", -classes: "onyx onyx-toolbar onyx-toolbar-inline", -create: function() { -this.inherited(arguments), this.hasClass("onyx-menu-toolbar") && enyo.platform.android >= 4 && this.applyStyle("position", "static"); -} -}); - -// Tooltip.js - -enyo.kind({ -name: "onyx.Tooltip", -kind: "onyx.Popup", -classes: "onyx-tooltip below left-arrow", -autoDismiss: !1, -showDelay: 500, -defaultLeft: -6, -handlers: { -onRequestShowTooltip: "requestShow", -onRequestHideTooltip: "requestHide" -}, -requestShow: function() { -return this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay), !0; -}, -cancelShow: function() { -clearTimeout(this.showJob); -}, -requestHide: function() { -return this.cancelShow(), this.inherited(arguments); -}, -showingChanged: function() { -this.cancelShow(), this.adjustPosition(!0), this.inherited(arguments); -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -adjustPosition: function(e) { -if (this.showing && this.hasNode()) { -var t = this.node.getBoundingClientRect(); -t.top + t.height > window.innerHeight ? (this.addRemoveClass("below", !1), this.addRemoveClass("above", !0)) : (this.addRemoveClass("above", !1), this.addRemoveClass("below", !0)), t.left + t.width > window.innerWidth && (this.applyPosition({ -"margin-left": -t.width, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !1), this.addRemoveClass("right-arrow", !0)); -} -}, -resizeHandler: function() { -this.applyPosition({ -"margin-left": this.defaultLeft, -bottom: "auto" -}), this.addRemoveClass("left-arrow", !0), this.addRemoveClass("right-arrow", !1), this.adjustPosition(!0), this.inherited(arguments); -} -}); - -// TooltipDecorator.js - -enyo.kind({ -name: "onyx.TooltipDecorator", -defaultKind: "onyx.Button", -classes: "onyx-popup-decorator", -handlers: { -onenter: "enter", -onleave: "leave" -}, -enter: function() { -this.requestShowTooltip(); -}, -leave: function() { -this.requestHideTooltip(); -}, -tap: function() { -this.requestHideTooltip(); -}, -requestShowTooltip: function() { -this.waterfallDown("onRequestShowTooltip"); -}, -requestHideTooltip: function() { -this.waterfallDown("onRequestHideTooltip"); -} -}); - -// ProgressBar.js - -enyo.kind({ -name: "onyx.ProgressBar", -classes: "onyx-progress-bar", -published: { -progress: 0, -min: 0, -max: 100, -barClasses: "", -showStripes: !0, -animateStripes: !0, -increment: 0 -}, -events: { -onAnimateProgressFinish: "" -}, -components: [ { -name: "progressAnimator", -kind: "Animator", -onStep: "progressAnimatorStep", -onEnd: "progressAnimatorComplete" -}, { -name: "bar", -classes: "onyx-progress-bar-bar" -} ], -create: function() { -this.inherited(arguments), this.progressChanged(), this.barClassesChanged(), this.showStripesChanged(), this.animateStripesChanged(); -}, -barClassesChanged: function(e) { -this.$.bar.removeClass(e), this.$.bar.addClass(this.barClasses); -}, -showStripesChanged: function() { -this.$.bar.addRemoveClass("striped", this.showStripes); -}, -animateStripesChanged: function() { -this.$.bar.addRemoveClass("animated", this.animateStripes); -}, -progressChanged: function() { -this.progress = this.clampValue(this.min, this.max, this.progress); -var e = this.calcPercent(this.progress); -this.updateBarPosition(e); -}, -calcIncrement: function(e) { -return Math.round(e / this.increment) * this.increment; -}, -clampValue: function(e, t, n) { -return Math.max(e, Math.min(n, t)); -}, -calcRatio: function(e) { -return (e - this.min) / (this.max - this.min); -}, -calcPercent: function(e) { -return this.calcRatio(e) * 100; -}, -updateBarPosition: function(e) { -this.$.bar.applyStyle("width", e + "%"); -}, -animateProgressTo: function(e) { -this.$.progressAnimator.play({ -startValue: this.progress, -endValue: e, -node: this.hasNode() -}); -}, -progressAnimatorStep: function(e) { -return this.setProgress(e.value), !0; -}, -progressAnimatorComplete: function(e) { -return this.doAnimateProgressFinish(e), !0; -} -}); - -// ProgressButton.js - -enyo.kind({ -name: "onyx.ProgressButton", -kind: "onyx.ProgressBar", -classes: "onyx-progress-button", -events: { -onCancel: "" -}, -components: [ { -name: "progressAnimator", -kind: "Animator", -onStep: "progressAnimatorStep", -onEnd: "progressAnimatorComplete" -}, { -name: "bar", -classes: "onyx-progress-bar-bar onyx-progress-button-bar" -}, { -name: "client", -classes: "onyx-progress-button-client" -}, { -kind: "onyx.Icon", -src: "$lib/onyx/images/progress-button-cancel.png", -classes: "onyx-progress-button-icon", -ontap: "cancelTap" -} ], -cancelTap: function() { -this.doCancel(); -} -}); - -// Scrim.js - -enyo.kind({ -name: "onyx.Scrim", -showing: !1, -classes: "onyx-scrim enyo-fit", -floating: !1, -create: function() { -this.inherited(arguments), this.zStack = [], this.floating && this.setParent(enyo.floatingLayer); -}, -showingChanged: function() { -this.floating && this.showing && !this.hasNode() && this.render(), this.inherited(arguments); -}, -addZIndex: function(e) { -enyo.indexOf(e, this.zStack) < 0 && this.zStack.push(e); -}, -removeZIndex: function(e) { -enyo.remove(e, this.zStack); -}, -showAtZIndex: function(e) { -this.addZIndex(e), e !== undefined && this.setZIndex(e), this.show(); -}, -hideAtZIndex: function(e) { -this.removeZIndex(e); -if (!this.zStack.length) this.hide(); else { -var t = this.zStack[this.zStack.length - 1]; -this.setZIndex(t); -} -}, -setZIndex: function(e) { -this.zIndex = e, this.applyStyle("z-index", e); -}, -make: function() { -return this; -} -}), enyo.kind({ -name: "onyx.scrimSingleton", -kind: null, -constructor: function(e, t) { -this.instanceName = e, enyo.setObject(this.instanceName, this), this.props = t || {}; -}, -make: function() { -var e = new onyx.Scrim(this.props); -return enyo.setObject(this.instanceName, e), e; -}, -showAtZIndex: function(e) { -var t = this.make(); -t.showAtZIndex(e); -}, -hideAtZIndex: enyo.nop, -show: function() { -var e = this.make(); -e.show(); -} -}), new onyx.scrimSingleton("onyx.scrim", { -floating: !0, -classes: "onyx-scrim-translucent" -}), new onyx.scrimSingleton("onyx.scrimTransparent", { -floating: !0, -classes: "onyx-scrim-transparent" -}); - -// Slider.js - -enyo.kind({ -name: "onyx.Slider", -kind: "onyx.ProgressBar", -classes: "onyx-slider", -published: { -value: 0, -lockBar: !0, -tappable: !0 -}, -events: { -onChange: "", -onChanging: "", -onAnimateFinish: "" -}, -showStripes: !1, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish" -}, -moreComponents: [ { -kind: "Animator", -onStep: "animatorStep", -onEnd: "animatorComplete" -}, { -classes: "onyx-slider-taparea" -}, { -name: "knob", -classes: "onyx-slider-knob" -} ], -create: function() { -this.inherited(arguments), enyo.platform.firefoxOS && (this.moreComponents[2].ondown = "down", this.moreComponents[2].onleave = "leave"), this.createComponents(this.moreComponents), this.valueChanged(); -}, -valueChanged: function() { -this.value = this.clampValue(this.min, this.max, this.value); -var e = this.calcPercent(this.value); -this.updateKnobPosition(e), this.lockBar && this.setProgress(this.value); -}, -updateKnobPosition: function(e) { -this.$.knob.applyStyle("left", e + "%"); -}, -calcKnobPosition: function(e) { -var t = e.clientX - this.hasNode().getBoundingClientRect().left; -return t / this.getBounds().width * (this.max - this.min) + this.min; -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = this.calcKnobPosition(t); -return n = this.increment ? this.calcIncrement(n) : n, this.setValue(n), this.doChanging({ -value: this.value -}), !0; -} -}, -dragfinish: function(e, t) { -return this.dragging = !1, t.preventTap(), this.doChange({ -value: this.value -}), !0; -}, -tap: function(e, t) { -if (this.tappable) { -var n = this.calcKnobPosition(t); -return n = this.increment ? this.calcIncrement(n) : n, this.tapped = !0, this.animateTo(n), !0; -} -}, -down: function(e, t) { -this.addClass("pressed"); -}, -leave: function(e, t) { -this.removeClass("pressed"); -}, -animateTo: function(e) { -this.$.animator.play({ -startValue: this.value, -endValue: e, -node: this.hasNode() -}); -}, -animatorStep: function(e) { -return this.setValue(e.value), !0; -}, -animatorComplete: function(e) { -return this.tapped && (this.tapped = !1, this.doChange({ -value: this.value -})), this.doAnimateFinish(e), !0; -} -}); - -// RangeSlider.js - -enyo.kind({ -name: "onyx.RangeSlider", -kind: "onyx.ProgressBar", -classes: "onyx-slider", -published: { -rangeMin: 0, -rangeMax: 100, -rangeStart: 0, -rangeEnd: 100, -beginValue: 0, -endValue: 0 -}, -events: { -onChange: "", -onChanging: "" -}, -showStripes: !1, -showLabels: !1, -handlers: { -ondragstart: "dragstart", -ondrag: "drag", -ondragfinish: "dragfinish", -ondown: "down" -}, -moreComponents: [ { -name: "startKnob", -classes: "onyx-slider-knob" -}, { -name: "endKnob", -classes: "onyx-slider-knob onyx-range-slider-knob" -} ], -create: function() { -this.inherited(arguments), this.createComponents(this.moreComponents), this.initControls(); -}, -rendered: function() { -this.inherited(arguments); -var e = this.calcPercent(this.beginValue); -this.updateBarPosition(e); -}, -initControls: function() { -this.$.bar.applyStyle("position", "relative"), this.refreshRangeSlider(), this.showLabels && (this.$.startKnob.createComponent({ -name: "startLabel", -kind: "onyx.RangeSliderKnobLabel" -}), this.$.endKnob.createComponent({ -name: "endLabel", -kind: "onyx.RangeSliderKnobLabel" -})); -}, -refreshRangeSlider: function() { -this.beginValue = this.calcKnobPercent(this.rangeStart), this.endValue = this.calcKnobPercent(this.rangeEnd), this.beginValueChanged(), this.endValueChanged(); -}, -calcKnobRatio: function(e) { -return (e - this.rangeMin) / (this.rangeMax - this.rangeMin); -}, -calcKnobPercent: function(e) { -return this.calcKnobRatio(e) * 100; -}, -beginValueChanged: function(e) { -if (e === undefined) { -var t = this.calcPercent(this.beginValue); -this.updateKnobPosition(t, this.$.startKnob); -} -}, -endValueChanged: function(e) { -if (e === undefined) { -var t = this.calcPercent(this.endValue); -this.updateKnobPosition(t, this.$.endKnob); -} -}, -calcKnobPosition: function(e) { -var t = e.clientX - this.hasNode().getBoundingClientRect().left; -return t / this.getBounds().width * (this.max - this.min) + this.min; -}, -updateKnobPosition: function(e, t) { -t.applyStyle("left", e + "%"), this.updateBarPosition(); -}, -updateBarPosition: function() { -if (this.$.startKnob !== undefined && this.$.endKnob !== undefined) { -var e = this.calcKnobPercent(this.rangeStart), t = this.calcKnobPercent(this.rangeEnd) - e; -this.$.bar.applyStyle("left", e + "%"), this.$.bar.applyStyle("width", t + "%"); -} -}, -calcRangeRatio: function(e) { -return e / 100 * (this.rangeMax - this.rangeMin) + this.rangeMin - this.increment / 2; -}, -swapZIndex: function(e) { -e === "startKnob" ? (this.$.startKnob.applyStyle("z-index", 1), this.$.endKnob.applyStyle("z-index", 0)) : e === "endKnob" && (this.$.startKnob.applyStyle("z-index", 0), this.$.endKnob.applyStyle("z-index", 1)); -}, -down: function(e, t) { -this.swapZIndex(e.name); -}, -dragstart: function(e, t) { -if (t.horizontal) return t.preventDefault(), this.dragging = !0, !0; -}, -drag: function(e, t) { -if (this.dragging) { -var n = this.calcKnobPosition(t), r, i, s; -if (e.name === "startKnob" && n >= 0) { -if (!(n <= this.endValue && t.xDirection === -1 || n <= this.endValue)) return this.drag(this.$.endKnob, t); -this.setBeginValue(n), r = this.calcRangeRatio(this.beginValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.startKnob), this.setRangeStart(i), this.doChanging({ -value: i -}); -} else if (e.name === "endKnob" && n <= 100) { -if (!(n >= this.beginValue && t.xDirection === 1 || n >= this.beginValue)) return this.drag(this.$.startKnob, t); -this.setEndValue(n), r = this.calcRangeRatio(this.endValue), i = this.increment ? this.calcIncrement(r + .5 * this.increment) : r, s = this.calcKnobPercent(i), this.updateKnobPosition(s, this.$.endKnob), this.setRangeEnd(i), this.doChanging({ -value: i -}); -} -return !0; -} -}, -dragfinish: function(e, t) { -this.dragging = !1, t.preventTap(); -var n; -return e.name === "startKnob" ? (n = this.calcRangeRatio(this.beginValue), this.doChange({ -value: n, -startChanged: !0 -})) : e.name === "endKnob" && (n = this.calcRangeRatio(this.endValue), this.doChange({ -value: n, -startChanged: !1 -})), !0; -}, -rangeMinChanged: function() { -this.refreshRangeSlider(); -}, -rangeMaxChanged: function() { -this.refreshRangeSlider(); -}, -rangeStartChanged: function() { -this.refreshRangeSlider(); -}, -rangeEndChanged: function() { -this.refreshRangeSlider(); -}, -setStartLabel: function(e) { -this.$.startKnob.waterfallDown("onSetLabel", e); -}, -setEndLabel: function(e) { -this.$.endKnob.waterfallDown("onSetLabel", e); -} -}), enyo.kind({ -name: "onyx.RangeSliderKnobLabel", -classes: "onyx-range-slider-label", -handlers: { -onSetLabel: "setLabel" -}, -setLabel: function(e, t) { -this.setContent(t); -} -}); - -// Item.js - -enyo.kind({ -name: "onyx.Item", -classes: "onyx-item", -tapHighlight: !0, -handlers: { -onhold: "hold", -onrelease: "release" -}, -hold: function(e, t) { -this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !0, t); -}, -release: function(e, t) { -this.tapHighlight && onyx.Item.addRemoveFlyweightClass(this.controlParent || this, "onyx-highlight", !1, t); -}, -statics: { -addRemoveFlyweightClass: function(e, t, n, r, i) { -var s = r.flyweight; -if (s) { -var o = i !== undefined ? i : r.index; -s.performOnRow(o, function() { -e.addRemoveClass(t, n); -}); -} -} -} -}); - -// Spinner.js - -enyo.kind({ -name: "onyx.Spinner", -classes: "onyx-spinner", -stop: function() { -this.setShowing(!1); -}, -start: function() { -this.setShowing(!0); -}, -toggle: function() { -this.setShowing(!this.getShowing()); -} -}); - -// MoreToolbar.js - -enyo.kind({ -name: "onyx.MoreToolbar", -classes: "onyx-toolbar onyx-more-toolbar", -menuClass: "", -movedClass: "", -layoutKind: "FittableColumnsLayout", -noStretch: !0, -handlers: { -onHide: "reflow" -}, -published: { -clientLayoutKind: "FittableColumnsLayout" -}, -tools: [ { -name: "client", -noStretch: !0, -fit: !0, -classes: "onyx-toolbar-inline" -}, { -name: "nard", -kind: "onyx.MenuDecorator", -showing: !1, -onActivate: "activated", -components: [ { -kind: "onyx.IconButton", -classes: "onyx-more-button" -}, { -name: "menu", -kind: "onyx.Menu", -scrolling: !1, -classes: "onyx-more-menu" -} ] -} ], -initComponents: function() { -this.menuClass && this.menuClass.length > 0 && !this.$.menu.hasClass(this.menuClass) && this.$.menu.addClass(this.menuClass), this.createChrome(this.tools), this.inherited(arguments), this.$.client.setLayoutKind(this.clientLayoutKind); -}, -clientLayoutKindChanged: function() { -this.$.client.setLayoutKind(this.clientLayoutKind); -}, -reflow: function() { -this.inherited(arguments), this.isContentOverflowing() ? (this.$.nard.show(), this.popItem() && this.reflow()) : this.tryPushItem() ? this.reflow() : this.$.menu.children.length || (this.$.nard.hide(), this.$.menu.hide()); -}, -activated: function(e, t) { -this.addRemoveClass("active", t.originator.active); -}, -popItem: function() { -var e = this.findCollapsibleItem(); -if (e) { -this.movedClass && this.movedClass.length > 0 && !e.hasClass(this.movedClass) && e.addClass(this.movedClass), this.$.menu.addChild(e, null); -var t = this.$.menu.hasNode(); -return t && e.hasNode() && e.insertNodeInParent(t), !0; -} -}, -pushItem: function() { -var e = this.$.menu.children, t = e[0]; -if (t) { -this.movedClass && this.movedClass.length > 0 && t.hasClass(this.movedClass) && t.removeClass(this.movedClass), this.$.client.addChild(t); -var n = this.$.client.hasNode(); -if (n && t.hasNode()) { -var r, i; -for (var s = 0; s < this.$.client.children.length; s++) { -var o = this.$.client.children[s]; -if (o.toolbarIndex !== undefined && o.toolbarIndex != s) { -r = o, i = s; -break; -} -} -if (r && r.hasNode()) { -t.insertNodeInParent(n, r.node); -var u = this.$.client.children.pop(); -this.$.client.children.splice(i, 0, u); -} else t.appendNodeToParent(n); -} -return !0; -} -}, -tryPushItem: function() { -if (this.pushItem()) { -if (!this.isContentOverflowing()) return !0; -this.popItem(); -} -}, -isContentOverflowing: function() { -if (this.$.client.hasNode()) { -var e = this.$.client.children, t = e[e.length - 1].hasNode(); -if (t) return this.$.client.reflow(), t.offsetLeft + t.offsetWidth > this.$.client.node.clientWidth; -} -}, -findCollapsibleItem: function() { -var e = this.$.client.children; -for (var t = e.length - 1; c = e[t]; t--) { -if (!c.unmoveable) return c; -c.toolbarIndex === undefined && (c.toolbarIndex = t); -} -} -}); - -// IntegerPicker.js - -enyo.kind({ -name: "onyx.IntegerPicker", -kind: "onyx.Picker", -published: { -value: 0, -min: 0, -max: 9 -}, -create: function() { -this.inherited(arguments), this.rangeChanged(); -}, -minChanged: function() { -this.destroyClientControls(), this.rangeChanged(), this.render(); -}, -maxChanged: function() { -this.destroyClientControls(), this.rangeChanged(), this.render(); -}, -rangeChanged: function() { -for (var e = this.min; e <= this.max; e++) this.createComponent({ -content: e, -active: e === this.value ? !0 : !1 -}); -}, -valueChanged: function(e) { -var t = this.getClientControls(), n = t.length; -this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; -for (var r = 0; r < n; r++) if (this.value === parseInt(t[r].content)) { -this.setSelected(t[r]); -break; -} -}, -selectedChanged: function(e) { -e && e.removeClass("selected"), this.selected && (this.selected.addClass("selected"), this.doChange({ -selected: this.selected, -content: this.selected.content -})), this.value = parseInt(this.selected.content); -} -}); - -// ContextualPopup.js - -enyo.kind({ -name: "onyx.ContextualPopup", -kind: "enyo.Popup", -modal: !0, -autoDismiss: !0, -floating: !1, -classes: "onyx-contextual-popup enyo-unselectable", -published: { -maxHeight: 100, -scrolling: !0, -title: undefined, -actionButtons: [] -}, -vertFlushMargin: 60, -horizFlushMargin: 50, -widePopup: 200, -longPopup: 200, -horizBuffer: 16, -events: { -onTap: "" -}, -handlers: { -onActivate: "itemActivated", -onRequestShowMenu: "requestShow", -onRequestHideMenu: "requestHide" -}, -components: [ { -name: "title", -classes: "onyx-contextual-popup-title" -}, { -classes: "onyx-contextual-popup-scroller", -components: [ { -name: "client", -kind: "enyo.Scroller", -vertical: "auto", -classes: "enyo-unselectable", -thumb: !1, -strategyKind: "TouchScrollStrategy" -} ] -}, { -name: "actionButtons", -classes: "onyx-contextual-popup-action-buttons" -} ], -scrollerName: "client", -create: function() { -this.inherited(arguments), this.maxHeightChanged(), this.titleChanged(), this.actionButtonsChanged(); -}, -getScroller: function() { -return this.$[this.scrollerName]; -}, -titleChanged: function() { -this.$.title.setContent(this.title); -}, -actionButtonsChanged: function() { -for (var e = 0; e < this.actionButtons.length; e++) this.$.actionButtons.createComponent({ -kind: "onyx.Button", -content: this.actionButtons[e].content, -classes: this.actionButtons[e].classes + " onyx-contextual-popup-action-button", -name: this.actionButtons[e].name ? this.actionButtons[e].name : "ActionButton" + e, -index: e, -tap: enyo.bind(this, this.tapHandler) -}); -}, -tapHandler: function(e, t) { -return t.actionButton = !0, t.popup = this, this.bubble("ontap", t), !0; -}, -maxHeightChanged: function() { -this.scrolling && this.getScroller().setMaxHeight(this.maxHeight + "px"); -}, -itemActivated: function(e, t) { -return t.originator.setActive(!1), !0; -}, -showingChanged: function() { -this.inherited(arguments), this.scrolling && this.getScroller().setShowing(this.showing), this.adjustPosition(); -}, -requestShow: function(e, t) { -var n = t.activator.hasNode(); -return n && (this.activatorOffset = this.getPageOffset(n)), this.show(), !0; -}, -applyPosition: function(e) { -var t = ""; -for (var n in e) t += n + ":" + e[n] + (isNaN(e[n]) ? "; " : "px; "); -this.addStyles(t); -}, -getPageOffset: function(e) { -var t = this.getBoundingRect(e), n = window.pageYOffset === undefined ? document.documentElement.scrollTop : window.pageYOffset, r = window.pageXOffset === undefined ? document.documentElement.scrollLeft : window.pageXOffset, i = t.height === undefined ? t.bottom - t.top : t.height, s = t.width === undefined ? t.right - t.left : t.width; -return { -top: t.top + n, -left: t.left + r, -height: i, -width: s -}; -}, -adjustPosition: function() { -if (this.showing && this.hasNode()) { -this.resetPositioning(); -var e = this.getViewWidth(), t = this.getViewHeight(), n = this.vertFlushMargin, r = t - this.vertFlushMargin, i = this.horizFlushMargin, s = e - this.horizFlushMargin; -if (this.activatorOffset.top + this.activatorOffset.height < n || this.activatorOffset.top > r) { -if (this.applyVerticalFlushPositioning(i, s)) return; -if (this.applyHorizontalFlushPositioning(i, s)) return; -if (this.applyVerticalPositioning()) return; -} else if (this.activatorOffset.left + this.activatorOffset.width < i || this.activatorOffset.left > s) if (this.applyHorizontalPositioning()) return; -var o = this.getBoundingRect(this.node); -if (o.width > this.widePopup) { -if (this.applyVerticalPositioning()) return; -} else if (o.height > this.longPopup && this.applyHorizontalPositioning()) return; -if (this.applyVerticalPositioning()) return; -if (this.applyHorizontalPositioning()) return; -} -}, -initVerticalPositioning: function() { -this.resetPositioning(), this.addClass("vertical"); -var e = this.getBoundingRect(this.node), t = this.getViewHeight(); -return this.floating ? this.activatorOffset.top < t / 2 ? (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height, -bottom: "auto" -}), this.addClass("below")) : (this.applyPosition({ -top: this.activatorOffset.top - e.height, -bottom: "auto" -}), this.addClass("above")) : e.top + e.height > t && t - e.bottom < e.top - e.height ? this.addClass("above") : this.addClass("below"), e = this.getBoundingRect(this.node), e.top + e.height > t || e.top < 0 ? !1 : !0; -}, -applyVerticalPositioning: function() { -if (!this.initVerticalPositioning()) return !1; -var e = this.getBoundingRect(this.node), t = this.getViewWidth(); -if (this.floating) { -var n = this.activatorOffset.left + this.activatorOffset.width / 2 - e.width / 2; -n + e.width > t ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width - e.width -}), this.addClass("left")) : n < 0 ? (this.applyPosition({ -left: this.activatorOffset.left -}), this.addClass("right")) : this.applyPosition({ -left: n -}); -} else { -var r = this.activatorOffset.left + this.activatorOffset.width / 2 - e.left - e.width / 2; -e.right + r > t ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width - e.right -}), this.addRemoveClass("left", !0)) : e.left + r < 0 ? this.addRemoveClass("right", !0) : this.applyPosition({ -left: r -}); -} -return !0; -}, -applyVerticalFlushPositioning: function(e, t) { -if (!this.initVerticalPositioning()) return !1; -var n = this.getBoundingRect(this.node), r = this.getViewWidth(); -return this.activatorOffset.left + this.activatorOffset.width / 2 < e ? (this.activatorOffset.left + this.activatorOffset.width / 2 < this.horizBuffer ? this.applyPosition({ -left: this.horizBuffer + (this.floating ? 0 : -n.left) -}) : this.applyPosition({ -left: this.activatorOffset.width / 2 + (this.floating ? this.activatorOffset.left : 0) -}), this.addClass("right"), this.addClass("corner"), !0) : this.activatorOffset.left + this.activatorOffset.width / 2 > t ? (this.activatorOffset.left + this.activatorOffset.width / 2 > r - this.horizBuffer ? this.applyPosition({ -left: r - this.horizBuffer - n.right -}) : this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width / 2 - n.right -}), this.addClass("left"), this.addClass("corner"), !0) : !1; -}, -initHorizontalPositioning: function() { -this.resetPositioning(); -var e = this.getBoundingRect(this.node), t = this.getViewWidth(); -return this.floating ? this.activatorOffset.left + this.activatorOffset.width < t / 2 ? (this.applyPosition({ -left: this.activatorOffset.left + this.activatorOffset.width -}), this.addRemoveClass("left", !0)) : (this.applyPosition({ -left: this.activatorOffset.left - e.width -}), this.addRemoveClass("right", !0)) : this.activatorOffset.left - e.width > 0 ? (this.applyPosition({ -left: this.activatorOffset.left - e.left - e.width -}), this.addRemoveClass("right", !0)) : (this.applyPosition({ -left: this.activatorOffset.width -}), this.addRemoveClass("left", !0)), this.addRemoveClass("horizontal", !0), e = this.getBoundingRect(this.node), e.left < 0 || e.left + e.width > t ? !1 : !0; -}, -applyHorizontalPositioning: function() { -if (!this.initHorizontalPositioning()) return !1; -var e = this.getBoundingRect(this.node), t = this.getViewHeight(), n = this.activatorOffset.top + this.activatorOffset.height / 2; -return this.floating ? n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 - e.height / 2, -bottom: "auto" -}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ -top: this.activatorOffset.top - this.activatorOffset.height, -bottom: "auto" -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: this.activatorOffset.top - e.height + this.activatorOffset.height * 2, -bottom: "auto" -}), this.addRemoveClass("low", !0)) : n >= t / 2 - .05 * t && n <= t / 2 + .05 * t ? this.applyPosition({ -top: (this.activatorOffset.height - e.height) / 2 -}) : this.activatorOffset.top + this.activatorOffset.height < t / 2 ? (this.applyPosition({ -top: -this.activatorOffset.height -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: e.top - e.height - this.activatorOffset.top + this.activatorOffset.height -}), this.addRemoveClass("low", !0)), !0; -}, -applyHorizontalFlushPositioning: function(e, t) { -if (!this.initHorizontalPositioning()) return !1; -var n = this.getBoundingRect(this.node), r = this.getViewWidth(); -return this.floating ? this.activatorOffset.top < innerHeight / 2 ? (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 -}), this.addRemoveClass("high", !0)) : (this.applyPosition({ -top: this.activatorOffset.top + this.activatorOffset.height / 2 - n.height -}), this.addRemoveClass("low", !0)) : n.top + n.height > innerHeight && innerHeight - n.bottom < n.top - n.height ? (this.applyPosition({ -top: n.top - n.height - this.activatorOffset.top - this.activatorOffset.height / 2 -}), this.addRemoveClass("low", !0)) : (this.applyPosition({ -top: this.activatorOffset.height / 2 -}), this.addRemoveClass("high", !0)), this.activatorOffset.left + this.activatorOffset.width < e ? (this.addClass("left"), this.addClass("corner"), !0) : this.activatorOffset.left > t ? (this.addClass("right"), this.addClass("corner"), !0) : !1; -}, -getBoundingRect: function(e) { -var t = e.getBoundingClientRect(); -return !t.width || !t.height ? { -left: t.left, -right: t.right, -top: t.top, -bottom: t.bottom, -width: t.right - t.left, -height: t.bottom - t.top -} : t; -}, -getViewHeight: function() { -return window.innerHeight === undefined ? document.documentElement.clientHeight : window.innerHeight; -}, -getViewWidth: function() { -return window.innerWidth === undefined ? document.documentElement.clientWidth : window.innerWidth; -}, -resetPositioning: function() { -this.removeClass("right"), this.removeClass("left"), this.removeClass("high"), this.removeClass("low"), this.removeClass("corner"), this.removeClass("below"), this.removeClass("above"), this.removeClass("vertical"), this.removeClass("horizontal"), this.applyPosition({ -left: "auto" -}), this.applyPosition({ -top: "auto" -}); -}, -resizeHandler: function() { -this.inherited(arguments), this.adjustPosition(); -}, -requestHide: function() { -this.setShowing(!1); -} -}); - -// App.js - -enyo.kind({ -name: "App", -kind: "FittableRows", -fit: !0, -components: [ { -kind: "onyx.Toolbar", -content: "Hello World" -}, { -kind: "enyo.Scroller", -fit: !0, -components: [ { -name: "main", -classes: "nice-padding", -allowHtml: !0 -} ] -}, { -kind: "onyx.Toolbar", -components: [ { -kind: "onyx.Button", -content: "Tap me", -ontap: "helloWorldTap" -} ] -} ], -helloWorldTap: function(e, t) { -this.$.main.addContent("The button was tapped.
    "); -} -}); diff --git a/deploy/bootplate/build/enyo.css b/deploy/bootplate/build/enyo.css deleted file mode 100644 index 6d05291..0000000 --- a/deploy/bootplate/build/enyo.css +++ /dev/null @@ -1,181 +0,0 @@ - -/* ../source/dom/dom.css */ - -/* things we always want */ -body { - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; -} - -/* allow hw-accelerated scrolling on platforms that support it */ -body.webkitOverflowScrolling { - -webkit-overflow-scrolling: touch; -} - -/* for apps */ -.enyo-document-fit { - margin: 0; - height: 100%; - /* note: giving html overflow: auto is odd and was only ever done to avoid duplication - however, android 4.04 sometimes does not hide nodes when their display is set to none - if document is overflow auto. - */ - position: relative; -} - -.enyo-body-fit { - margin: 0; - height: 100%; - /* helps prevent ios page scroll */ - overflow: auto; - position: relative; -} - -.enyo-no-touch-action { - -ms-touch-action: none; -} - -/* reset */ - -button { - font-size: inherit; - font-family: inherit; -} -button::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* user selection */ - -.enyo-unselectable { - cursor: default; - -ms-user-select: none; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; -} - -.enyo-unselectable::selection, .enyo-unselectable ::selection { - color: transparent; -} - -.enyo-selectable { - cursor: auto; - -ms-user-select: element; - -webkit-user-select: text; - -moz-user-select: text; - user-select: text; -} - -.enyo-selectable::selection, .enyo-selectable ::selection { - background: #3297FD; - color: #FFF; -} - -/* layout */ - -body .enyo-fit { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.enyo-clip { - overflow: hidden; -} - -.enyo-border-box { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* compositing */ - -.enyo-composite { - -webkit-transform: translateZ(0); - -moz-transform: translateZ(0); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - transform: translateZ(0); -} - - -/* ../source/touch/Thumb.css */ - -.enyo-thumb { - position: absolute; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; - background: #333; - border: 1px solid #666; - opacity: 0.75; - z-index: 1; -} - -.enyo-vthumb { - top: 0; - right: 2px; - width: 4px; -} - -.enyo-hthumb { - left: 0; - bottom: 2px; - height: 4px; -} - - -/* ../source/touch/Scroller.css */ - -.enyo-scroller { - position: relative; -} - -.enyo-fit.enyo-scroller { - position: absolute; -} - -.enyo-touch-scroller { - overflow: hidden; -} - -.enyo-touch-strategy-container { - overflow: hidden; -} - -.enyo-scrollee-fit { - height: 100%; -} - -/* ../source/ui/ui.css */ - -.enyo-inline, .enyo-tool-decorator { - display: inline-block; -} - -.enyo-children-inline > *, .enyo-tool-decorator > * { - display: inline-block; -} - -.enyo-children-middle > *, .enyo-tool-decorator > * { - vertical-align: middle; -} - -.enyo-positioned { - position: relative; -} - -.enyo-fill { - position: relative; - width: 100%; - height: 100%; -} - -.enyo-popup { - position: absolute; - z-index: 10; -} diff --git a/deploy/bootplate/build/enyo.js b/deploy/bootplate/build/enyo.js deleted file mode 100644 index e565f50..0000000 --- a/deploy/bootplate/build/enyo.js +++ /dev/null @@ -1,4283 +0,0 @@ - -// enyo.js - -(function() { -var e = "enyo.js"; -enyo = window.enyo || {}, enyo.locateScript = function(e) { -var t = document.getElementsByTagName("script"); -for (var n = t.length - 1, r, i, s = e.length; n >= 0 && (r = t[n]); n--) if (!r.located) { -i = r.getAttribute("src") || ""; -if (i.slice(-s) == e) return r.located = !0, { -path: i.slice(0, Math.max(0, i.lastIndexOf("/"))), -node: r -}; -} -}, enyo.args = enyo.args || {}; -var t = enyo.locateScript(e); -if (t) { -enyo.args.root = (enyo.args.root || t.path).replace("/source", ""); -for (var n = 0, r = t.node.attributes.length, i; n < r && (i = t.node.attributes.item(n)); n++) enyo.args[i.nodeName] = i.value; -} -})(); - -// ../../loader.js - -(function() { -enyo = window.enyo || {}, enyo.pathResolverFactory = function() { -this.paths = {}; -}, enyo.pathResolverFactory.prototype = { -addPath: function(e, t) { -return this.paths[e] = t; -}, -addPaths: function(e) { -if (e) for (var t in e) this.addPath(t, e[t]); -}, -includeTrailingSlash: function(e) { -return e && e.slice(-1) !== "/" ? e + "/" : e; -}, -rewritePattern: /\$([^\/\\]*)(\/)?/g, -rewrite: function(e) { -var t, n = this.includeTrailingSlash, r = this.paths, i = function(e, i) { -return t = !0, n(r[i]) || ""; -}, s = e; -do t = !1, s = s.replace(this.rewritePattern, i); while (t); -return s; -} -}, enyo.path = new enyo.pathResolverFactory, enyo.loaderFactory = function(e, t) { -this.machine = e, this.packages = [], this.modules = [], this.sheets = [], this.stack = [], this.pathResolver = t || enyo.path, this.packageName = "", this.packageFolder = "", this.finishCallbacks = {}; -}, enyo.loaderFactory.prototype = { -verbose: !1, -loadScript: function(e) { -this.machine.script(e); -}, -loadSheet: function(e) { -this.machine.sheet(e); -}, -loadPackage: function(e) { -this.machine.script(e); -}, -report: function() {}, -load: function() { -this.more({ -index: 0, -depends: arguments || [] -}); -}, -more: function(e) { -if (e && this.continueBlock(e)) return; -var t = this.stack.pop(); -t ? (this.verbose && console.groupEnd("* finish package (" + (t.packageName || "anon") + ")"), this.packageFolder = t.folder, this.packageName = "", this.more(t)) : this.finish(); -}, -finish: function() { -this.packageFolder = "", this.verbose && console.log("-------------- fini"); -for (var e in this.finishCallbacks) this.finishCallbacks[e] && (this.finishCallbacks[e](), this.finishCallbacks[e] = null); -}, -continueBlock: function(e) { -while (e.index < e.depends.length) { -var t = e.depends[e.index++]; -if (t) if (typeof t == "string") { -if (this.require(t, e)) return !0; -} else this.pathResolver.addPaths(t); -} -}, -require: function(e, t) { -var n = this.pathResolver.rewrite(e), r = this.getPathPrefix(e); -n = r + n; -if (n.slice(-4) == ".css" || n.slice(-5) == ".less") this.verbose && console.log("+ stylesheet: [" + r + "][" + e + "]"), this.requireStylesheet(n); else { -if (n.slice(-3) != ".js" || n.slice(-10) == "package.js") return this.requirePackage(n, t), !0; -this.verbose && console.log("+ module: [" + r + "][" + e + "]"), this.requireScript(e, n); -} -}, -getPathPrefix: function(e) { -var t = e.slice(0, 1); -return t != "/" && t != "\\" && t != "$" && !/^https?:/i.test(e) ? this.packageFolder : ""; -}, -requireStylesheet: function(e) { -this.sheets.push(e), this.loadSheet(e); -}, -requireScript: function(e, t) { -this.modules.push({ -packageName: this.packageName, -rawPath: e, -path: t -}), this.loadScript(t); -}, -decodePackagePath: function(e) { -var t = "", n = "", r = "", i = "package.js", s = e.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"), o, u; -if (s.length) { -var a = s.pop() || s.pop() || ""; -a.slice(-i.length) !== i ? s.push(a) : i = a, r = s.join("/"), r = r ? r + "/" : "", i = r + i; -for (o = s.length - 1; o >= 0; o--) if (s[o] == "source") { -s.splice(o, 1); -break; -} -n = s.join("/"); -for (o = s.length - 1; u = s[o]; o--) if (u == "lib" || u == "enyo") { -s = s.slice(o + 1); -break; -} -for (o = s.length - 1; u = s[o]; o--) (u == ".." || u == ".") && s.splice(o, 1); -t = s.join("-"); -} -return { -alias: t, -target: n, -folder: r, -manifest: i -}; -}, -aliasPackage: function(e) { -var t = this.decodePackagePath(e); -this.manifest = t.manifest, t.alias && (this.pathResolver.addPath(t.alias, t.target), this.packageName = t.alias, this.packages.push({ -name: t.alias, -folder: t.folder -})), this.packageFolder = t.folder; -}, -requirePackage: function(e, t) { -t.folder = this.packageFolder, this.aliasPackage(e), t.packageName = this.packageName, this.stack.push(t), this.report("loading package", this.packageName), this.verbose && console.group("* start package [" + this.packageName + "]"), this.loadPackage(this.manifest); -} -}; -})(); - -// boot.js - -enyo.execUnsafeLocalFunction = function(e) { -typeof MSApp == "undefined" ? e() : MSApp.execUnsafeLocalFunction(e); -}, enyo.machine = { -sheet: function(e) { -var t = "text/css", n = "stylesheet", r = e.slice(-5) == ".less"; -r && (window.less ? (t = "text/less", n = "stylesheet/less") : e = e.slice(0, e.length - 4) + "css"); -var i; -enyo.runtimeLoading || r ? (i = document.createElement("link"), i.href = e, i.media = "screen", i.rel = n, i.type = t, document.getElementsByTagName("head")[0].appendChild(i)) : (i = function() { -document.write(''); -}, enyo.execUnsafeLocalFunction(i)), r && window.less && (less.sheets.push(i), enyo.loader.finishCallbacks.lessRefresh || (enyo.loader.finishCallbacks.lessRefresh = function() { -less.refresh(!0); -})); -}, -script: function(e, t, n) { -if (!enyo.runtimeLoading) document.write(' - - - - - - diff --git a/deploy/bootplate/lib/onyx/LICENSE-2.0.txt b/deploy/bootplate/lib/onyx/LICENSE-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/deploy/bootplate/lib/onyx/LICENSE-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/deploy/bootplate/lib/onyx/images/checkbox.png b/deploy/bootplate/lib/onyx/images/checkbox.png deleted file mode 100644 index 9176591af4192b5f8fc9d1f66f77da078ae4ab5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5462 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 KMNUMnLSTZHmo(J? diff --git a/deploy/bootplate/lib/onyx/images/gradient-invert.png b/deploy/bootplate/lib/onyx/images/gradient-invert.png deleted file mode 100644 index 44ab5ac084b0962fb8d709e84f158ec880744e6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<7!3HE7BzD~bQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F5`$3q|f;CtLC@59p8c`CQpH@h~YuU)o|cQ6aCV1LzC}Pgg&ebxsLQ0EN_9@c;k- diff --git a/deploy/bootplate/lib/onyx/images/gradient.png b/deploy/bootplate/lib/onyx/images/gradient.png deleted file mode 100644 index 58562587c62b21c388f8957ad6e0370dba70487b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 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 diff --git a/deploy/bootplate/lib/onyx/images/search-input-cancel.png b/deploy/bootplate/lib/onyx/images/search-input-cancel.png deleted file mode 100644 index 8056b4a471e0a7da1e438c7d5cc9ef3a9862a813..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{doXXw8qoL zF~q|E?c{^J2NXD5_m;K2ySQ}j!6UXlF-xDC&r)DrS?=4Bc~t#_V$0s79`;Bj?UdzV zf`9U#f3RK_n!RCm*$wtn33t^i9UOLjW(ZBNST85=GK95iYsb&z55cF6Y%VEH4B)F$ z{>}P2g?$%Wa=;Qz<-^~%+VHnAEc;d8GBNA4$633pEE5f`_ypfX~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/deploy/bootplate/lib/onyx/images/slider-handle.png b/deploy/bootplate/lib/onyx/images/slider-handle.png deleted file mode 100644 index 09e12fbd19e1ff9e3faef8f2a2baaffab78688ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3095 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 Pn1F;$An(;T&^-PCGf5vc diff --git a/enyo/CONTRIBUTING md b/enyo/CONTRIBUTING md deleted file mode 100644 index e191d77..0000000 --- a/enyo/CONTRIBUTING md +++ /dev/null @@ -1,10 +0,0 @@ -# Contributions - -Contributions are welcome for Enyo and its associated libraries including onyx and layout. - -Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details -on our contribution policy and guidelines for use of the Enyo-DCO-1.1-Signed-off-by -line in your commits and pull requests. - -If you're interested in introducing new kinds, you might also consider hosting your own repo -and contributing to the [Enyo community gallery](http://enyojs.com/gallery). \ No newline at end of file diff --git a/enyo/LICENSE-2.0.txt b/enyo/LICENSE-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/enyo/LICENSE-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/enyo/README.md b/enyo/README.md deleted file mode 100644 index fef69dc..0000000 --- a/enyo/README.md +++ /dev/null @@ -1,146 +0,0 @@ -### Looking for the issue tracker? -It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). - ---- - -# Quick Info - -## Core - -This repository contains Enyo core. We've pared it down to the essentials, so folks can work at the metal. Widget libraries, g11n code, and other fancy bits are optional packages. - -## Lib - -Packages should go in a folder named _lib_ (e.g. the _extra_ or _canvas_ repositories on GitHub). _lib_ is a magic name that enyo uses to work with add-on packages. It's recommended you create a _lib_ folder as sibling to _enyo_ and keep your packages there, but you can make as many _lib_ folders as you like and put them anywhere. - -## Warning about file:// - -_Note_: in Chrome, various samples will not work from file:// because of Chrome's security policy. Run from a local http server, use the --allow-file-access-from-files in Chrome, or use the online versions at http://enyojs.com. - -# What Is Enyo - -Enyo is an object-oriented JavaScript application framework emphasizing modularity and encapsulation. Enyo is suitable for small and large-scale applications. - -Enyo up to 1.x was the underlying framework used to develop applications for HP's TouchPad tablet. Enyo as shipped on the TouchPad included an complete set of user interface components and service wrappers. What you will find here is Enyo 2, what we informally call _core_: the primary infrastructure needed to support any number of Enyo-based libraries. Not to worry, Enyo 1.x itself is open-source licensed, and work is progressing on packaging up those controls and goodies to work with Enyo 2. - -Enyo was designed from the beginning to be highly extensible. This repository reflects a small working set of code, that can be expanded with any number of libraries or plugins. - -Enyo 2 is lightweight, easy to digest, and powerful. - -# What Do I Get - -The core code includes the Enyo kernel, the DOM extensions, some Ajax (XHR) tools, and basic wrapper kinds for a lot of DOM form elements. These things are actually separable (it's easy to make micro-builds of Enyo), but we believe this is a useful working set. - -The Enyo 2 kernel provides a modularity concept (Component) and a view concept (UiComponent). The DOM aspect includes a widget concept (Control) and an extensible event system (Dispatcher). The Ajax package includes basic xhr functionality and an implementation of xhr as a Component (Ajax). The touch package provides platform-optimized scrollers, while the UI package provides base kinds for common controls like buttons and popups. - -Just these pieces are sufficient to create large applications using the Enyo encapsulation model. Developers that want only this low-level code are encouraged to roll-their-own. For those that want a richer set of tools, there are some pre-built libraries already available, and much more on the way. - -# Why Do I Care - -First is our emphasis on cross-platform: Enyo core works on both desktop and mobile browsers. - -Second is Enyo's building block approach to applications. Each piece of an application is a Component, and Components are constructed out of other Components. - -For example, it's easy to define a combination of an `` tag with a `

    Hello From Enyo
    -``` - -Now, the good parts start when you combine more than one Control, e.g. - -```javascript -new enyo.Control({ - components: [ - {content: "Hello From Enyo"}, - {tag: "hr"} - ] -}).renderInto(document.body); -``` - -This Control now encapsulates two Controls into one scope (we can encapsulate any type of Component, that's why the property is called _components_. Controls are one kind of Component.) The outer Control is responsible for the encapsulated components: it manages their lifecycle, listens to their messages, and maintains references to them. For example: - -```javascript -new enyo.Control({ - components: [ - {name: "hello", content: "Hello From Enyo", ontap: "helloTap"}, - {tag: "hr"} - ], - helloTap: function() { - this.$.hello.addStyles("color: red"); - } -}).renderInto(document.body); -``` - -Here we've given one of the components a name ('hello') and told it to send a 'helloTap' message when it's tapped (tap is basically the same as the DOM click event, but it works in both mouse and touch environments). The '$' property is a hash that references all the sub-components (we don't store these references directly on _this_ to avoid name conflicts). Notice there is no add/remove machinery to listen to this event, that's all taken care of. - -The main point is that 'hello' and the 'hr', their references and behavior, are completely contained inside the outer control. Now, to re-use this, we need to make it a prototype. - -Enyo contains a constructor/prototype-generator that we call enyo.kind. Constructors that enyo.kind produces are called _kinds_. Kinds are not magic, they are just regular old JavaScript constructors. Using the enyo.kind factory however allows us to remove boilerplate from our prototype generation (DRY) and have compact syntax. We can convert the Control above to a kind like so: - -```javascript -enyo.kind({ - name: "Hello", - kind: enyo.Control, - components: [ - {name: "hello", content: "Hello From Enyo", ontap: "helloTap"}, - {tag: "hr"} - ], - helloTap: function() { - this.$.hello.addStyles("color: red"); - } -}); -// make two, they're small -new enyo.Control({ - component: [ {kind: "Hello"}, {kind: "Hello"} ] - }).renderInto(document.body); -``` - -The code above creates a new kind called "Hello" derived from enyo.Control. It contains some components and some behavior. I can create as many "Hello" objects as I want, each instance is independent, and the user of a "Hello" doesn't need to know anything about its internals. - -This ability to define encapsulated objects and behavior (Components) and to re-use those encapsulations as prototypes (kinds) is money. diff --git a/enyo/enyo.js b/enyo/enyo.js deleted file mode 100644 index 596eae7..0000000 --- a/enyo/enyo.js +++ /dev/null @@ -1,41 +0,0 @@ -(function() { - // enyo can use information from the script tag that loads this bootstrap file - var thisScript = "enyo.js"; - - enyo = window.enyo || {}; - - enyo.locateScript = function(inName) { - var scripts = document.getElementsByTagName("script"); - for (var i=scripts.length-1, s, src, l=inName.length; (i>=0) && (s=scripts[i]); i--) { - if (!s.located) { - src = s.getAttribute("src") || ""; - if (src.slice(-l) == inName) { - s.located = true; - return {path: src.slice(0, Math.max(0, src.lastIndexOf("/"))), node: s}; - } - } - } - }; - - enyo.args = enyo.args || {}; - - var tag = enyo.locateScript(thisScript); - if (tag) { - // infer the framework path from the document, unless the user has specified one explicitly - enyo.args.root = (enyo.args.root || tag.path); - // all attributes of the bootstrap script tag become enyo.args - for (var i=0, al = tag.node.attributes.length, it; (i < al) && (it = tag.node.attributes.item(i)); i++) { - enyo.args[it.nodeName] = it.value; - } - } - - var root = enyo.args.root; - - var script = function(inSrc) { - document.write(''); - }; - - script("../../loader.js"); - script("boot.js"); - script("../package.js"); -})(); diff --git a/enyo/loader.js b/enyo/loader.js deleted file mode 100644 index 931c8da..0000000 --- a/enyo/loader.js +++ /dev/null @@ -1,302 +0,0 @@ -(function() { - enyo = window.enyo || {}; - - enyo.pathResolverFactory = function() { - this.paths = {}; - }; - - enyo.pathResolverFactory.prototype = { - addPath: function(inName, inPath) { - return this.paths[inName] = inPath; - }, - addPaths: function(inPaths) { - if (inPaths) { - for (var n in inPaths) { - this.addPath(n, inPaths[n]); - } - } - }, - includeTrailingSlash: function(inPath) { - return (inPath && inPath.slice(-1) !== "/") ? inPath + "/" : inPath; - }, - // match $name - rewritePattern: /\$([^\/\\]*)(\/)?/g, - // replace macros of the form $pathname with the mapped value of paths.pathname - rewrite: function (inPath) { - var working, its = this.includeTrailingSlash, paths = this.paths; - var fn = function(macro, name) { - working = true; - return its(paths[name]) || ''; - }; - var result = inPath; - do { - working = false; - result = result.replace(this.rewritePattern, fn); - } while (working); - return result; - } - }; - - enyo.path = new enyo.pathResolverFactory(); - - enyo.loaderFactory = function(inMachine, inPathResolver) { - this.machine = inMachine; - // package information - this.packages = []; - // module information - this.modules = []; - // stylesheet paths - this.sheets = []; - // (protected) internal dependency stack - this.stack = []; - this.pathResolver = inPathResolver || enyo.path; - this.packageName = ""; - this.packageFolder = ""; - this.finishCallbacks = {}; - }; - - enyo.loaderFactory.prototype = { - verbose: false, - loadScript: function(inScript) { - this.machine.script(inScript); - }, - loadSheet: function(inSheet) { - this.machine.sheet(inSheet); - }, - loadPackage: function(inPackage) { - this.machine.script(inPackage); - }, - report: function() { - }, - // - load: function(/**/) { - // begin processing dependencies - this.more({ - index: 0, - depends: arguments || [] - }); - }, - more: function(inBlock) { - // a 'block' is a dependency list with a bookmark - // the bookmark (index) allows us to interrupt - // processing and then continue asynchronously. - if (inBlock) { - // returns true if this block has asynchronous requirements - // in that case, we unwind the stack. The asynchronous loader - // must provide the continuation (by calling 'more' again). - if (this.continueBlock(inBlock)) { - return; - } - } - // A package is now complete. Pop the block that was interrupted for that package (if any). - var block = this.stack.pop(); - if (block) { - // block.packageName is the name of the package that interrupted us - //this.report("finished package", block.packageName); - if (this.verbose) { - console.groupEnd("* finish package (" + (block.packageName || "anon") + ")"); - } - // cache the folder for the currently processing package - this.packageFolder = block.folder; - // no current package - this.packageName = ""; - // process this new block - this.more(block); - } else { - this.finish(); - } - }, - finish: function() { - this.packageFolder = ""; - if (this.verbose) { - console.log("-------------- fini"); - } - for (var i in this.finishCallbacks) { - if (this.finishCallbacks[i]) { - this.finishCallbacks[i](); - this.finishCallbacks[i] = null; - } - } - }, - continueBlock: function(inBlock) { - while (inBlock.index < inBlock.depends.length) { - var d = inBlock.depends[inBlock.index++]; - if (d) { - if (typeof d == "string") { - if (this.require(d, inBlock)) { - // return true to indicate we need to interrupt - // processing until asynchronous file load completes - // the load process itself must provide the - // continuation - return true; - } - } else { - this.pathResolver.addPaths(d); - } - } - } - }, - require: function(inPath, inBlock) { - // process aliases - var path = this.pathResolver.rewrite(inPath); - // get path root - var prefix = this.getPathPrefix(inPath); - // assemble path - path = prefix + path; - // process path - if ((path.slice(-4) == ".css") || (path.slice(-5) == ".less")) { - if (this.verbose) { - console.log("+ stylesheet: [" + prefix + "][" + inPath + "]"); - } - this.requireStylesheet(path); - } else if (path.slice(-3) == ".js" && path.slice(-10) != "package.js") { - if (this.verbose) { - console.log("+ module: [" + prefix + "][" + inPath + "]"); - } - this.requireScript(inPath, path); - } else { - // package - this.requirePackage(path, inBlock); - // return true to indicate a package was located and - // we need to interrupt further processing until it's completed - return true; - } - }, - getPathPrefix: function(inPath) { - var delim = inPath.slice(0, 1); - if ((delim != "/") && (delim != "\\") && (delim != "$") && !/^https?:/i.test(inPath)) { - return this.packageFolder; - } - return ""; - }, - requireStylesheet: function(inPath) { - // stylesheet - this.sheets.push(inPath); - this.loadSheet(inPath); - }, - requireScript: function(inRawPath, inPath) { - // script file - this.modules.push({ - packageName: this.packageName, - rawPath: inRawPath, - path: inPath - }); - this.loadScript(inPath); - }, - decodePackagePath: function(inPath) { - // A package path can be encoded in two ways: - // - // 1. [folder] - // 2. [folder]/[*package.js] - // - // Note: manifest file name must end in "package.js" - // - var alias = '', target = '', folder = '', manifest = 'package.js'; - // convert back slashes to forward slashes, remove double slashes, split on slash - var parts = inPath.replace(/\\/g, "/").replace(/\/\//g, "/").replace(/:\//, "://").split("/"); - var i, p; - if (parts.length) { - // if inPath has a trailing slash, parts has an empty string which we pop off and ignore - var name = parts.pop() || parts.pop() || ""; - // test if name includes the manifest tag - if (name.slice(-manifest.length) !== manifest) { - // if not a manifest name, it's part of the folder path - parts.push(name); - } else { - // otherwise this is the manifest name - manifest = name; - } - // - folder = parts.join("/"); - folder = (folder ? folder + "/" : ""); - manifest = folder + manifest; - // - // build friendly aliasing: - // - for (i=parts.length-1; i >= 0; i--) { - if (parts[i] == "source") { - parts.splice(i, 1); - break; - } - } - target = parts.join("/"); - // - // portable aliasing: - // - // packages that are rooted at a folder named "enyo" or "lib" do not - // include that root path in their alias - // - // remove */lib or */enyo prefix - // - // e.g. foo/bar/baz/lib/zot -> zot package - // - for (i=parts.length-1; (p=parts[i]); i--) { - if (p == "lib" || p == "enyo") { - parts = parts.slice(i+1); - break; - } - } - // remove ".." and "." - for (i=parts.length-1; (p=parts[i]); i--) { - if (p == ".." || p == ".") { - parts.splice(i, 1); - } - } - // - alias = parts.join("-"); - } - return { - alias: alias, - target: target, - folder: folder, - manifest: manifest - }; - }, - aliasPackage: function(inPath) { - var parts = this.decodePackagePath(inPath); - // cache manifest path - this.manifest = parts.manifest; - // cache package info for named packages - if (parts.alias) { - // debug only - /* - var old = this.pathResolver.paths[parts.name]; - if (old && old != parts.folder) { - this.verbose && console.warn("mapping alias [" + parts.name + "] to [" + parts.folder + "] replacing [" + old + "]"); - } - this.verbose && console.log("mapping alias [" + parts.name + "] to [" + parts.folder + "]"); - */ - // - // create a path alias for this package - this.pathResolver.addPath(parts.alias, parts.target); - // - // cache current name - this.packageName = parts.alias; - // cache package information - this.packages.push({ - name: parts.alias, - folder: parts.folder - }); - } - // cache current folder - this.packageFolder = parts.folder; - }, - requirePackage: function(inPath, inBlock) { - // cache the interrupted packageFolder - inBlock.folder = this.packageFolder; - this.aliasPackage(inPath); - // cache the name of the package 'inBlock' is loading now - inBlock.packageName = this.packageName; - // push inBlock on the continuation stack - this.stack.push(inBlock); - // console/user reporting - this.report("loading package", this.packageName); - if (this.verbose) { - console.group("* start package [" + this.packageName + "]"); - } - // load the actual package. the package MUST call a continuation function - // or the process will halt. - this.loadPackage(this.manifest); - } - }; -})(); \ No newline at end of file diff --git a/enyo/minify/minify.bat b/enyo/minify/minify.bat deleted file mode 100644 index 2c42a20..0000000 --- a/enyo/minify/minify.bat +++ /dev/null @@ -1,6 +0,0 @@ -@ECHO OFF -REM FIXME: minify has a problem if 'package.js' is not in CWD, hence push, cd, pop -PUSHD "%CD%" -CD "%~dp0" -CALL ..\tools\minify.bat package.js -no-alias -output ..\..\build\enyo %* -POPD diff --git a/enyo/minify/minify.sh b/enyo/minify/minify.sh deleted file mode 100644 index ca409c8..0000000 --- a/enyo/minify/minify.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd $(dirname $0) -../tools/minify.sh package.js -no-alias -output ../../build/enyo diff --git a/enyo/minify/package.js b/enyo/minify/package.js deleted file mode 100644 index 02ba830..0000000 --- a/enyo/minify/package.js +++ /dev/null @@ -1,4 +0,0 @@ -enyo.depends( - "../source/boot", - "../source" -); diff --git a/enyo/package.json b/enyo/package.json deleted file mode 100644 index 594d4d3..0000000 --- a/enyo/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "enyo", - "filename": "enyo.js", - "version": "2.2.0", - "description":"Enyo is an open source object-oriented JavaScript framework emphasizing encapsulation and modularity. Enyo contains everything you need to create a fast, scalable mobile or web application.", - "homepage": "http://enyojs.com/", - "keywords": [ "framework", "toolkit", "components", "mobile", "webOS" ], - "maintainers": [{ - "name": "Enyo JS Framework Team (HP)", - "web": "http://enyojs.com/" - }], - "licenses": [{ - "type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" - }], - "bugs": "https://jira.enyojs.com/", - "repositories": [{ - "type": "git", "url": "http://github.com/enyojs/enyo" - }] -} diff --git a/enyo/samples/AjaxSample.css b/enyo/samples/AjaxSample.css deleted file mode 100644 index 850c658..0000000 --- a/enyo/samples/AjaxSample.css +++ /dev/null @@ -1,14 +0,0 @@ -.ajax-sample { - padding: 15px; -} - -.ajax-sample-source { - padding:15px; - font-family: monospace; - font-size: 12px; - white-space: pre-wrap; - box-sizing: border-box; - width:100%; - height:100%; - margin-top:15px; -} diff --git a/enyo/samples/AjaxSample.html b/enyo/samples/AjaxSample.html deleted file mode 100644 index 7a3a758..0000000 --- a/enyo/samples/AjaxSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - AJAX Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/AjaxSample.js b/enyo/samples/AjaxSample.js deleted file mode 100644 index d04d972..0000000 --- a/enyo/samples/AjaxSample.js +++ /dev/null @@ -1,37 +0,0 @@ -enyo.kind({ - name: "enyo.sample.AjaxSample", - kind: "FittableRows", - classes: "enyo-fit ajax-sample", - components: [ - {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ - {content: "YQL: "}, - {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, - {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} - ]}, - {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ - {content: "URL: "}, - {kind: "onyx.Input", name:"baseUrl", fit:true, value:'http://query.yahooapis.com/v1/public/yql?format=json'} - ]}, - {kind: "onyx.TextArea", fit:true, classes:"ajax-sample-source"} - ], - fetch: function() { - var ajax = new enyo.Ajax({ - url: this.$.baseUrl.getValue() - }); - // send parameters the remote service using the 'go()' method - ajax.go({ - q: this.$.query.getValue() - }); - // attach responders to the transaction object - ajax.response(this, "processResponse"); - // handle error - ajax.error(this, "processError"); - }, - processResponse: function(inSender, inResponse) { - // do something with it - this.$.textArea.setValue(JSON.stringify(inResponse, null, 2)); - }, - processError: function(inSender, inResponse) { - alert("Error!"); - } -}); \ No newline at end of file diff --git a/enyo/samples/GestureSample.css b/enyo/samples/GestureSample.css deleted file mode 100644 index bdf6c08..0000000 --- a/enyo/samples/GestureSample.css +++ /dev/null @@ -1,57 +0,0 @@ -.gesture-sample { - padding: 15px; -} - -.gesture-sample > * { - margin-bottom:10px; -} - -.gesture-sample-pad { - border-radius: 5px; - background-color: #888; - color: #686868; - text-shadow:#AAA 0px 1px 0, #000 0 -1px 0; - text-align:center; - padding-top:15%; - font-size:30px; - overflow:hidden; -} - -.gesture-sample-note { - font-size:15px; - text-shadow:none; -} - -.gesture-sample-padded > * { - padding:5px; -} - -.gesture-sample-left > * { - text-align:left; -} - -.gesture-sample-setting { - font-size: 15px; - padding: 10px; - min-height: 30px; - line-height: 30px; -} -.gesture-sample-setting > * { - display: inline-block; -} - -.gesture-sample-setting > :last-child { - float: right; -} - -@media all and (max-height:600px) { - .gesture-sample-truncate { - width:100%; - word-wrap:normal; - white-space:nowrap; - overflow:hidden; - -o-text-overflow:ellipsis; - text-overflow:ellipsis; - } -} - diff --git a/enyo/samples/GestureSample.html b/enyo/samples/GestureSample.html deleted file mode 100644 index 544ee8e..0000000 --- a/enyo/samples/GestureSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Gesture Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/GestureSample.js b/enyo/samples/GestureSample.js deleted file mode 100644 index 6a64b27..0000000 --- a/enyo/samples/GestureSample.js +++ /dev/null @@ -1,198 +0,0 @@ -enyo.kind({ - name: "enyo.sample.GestureSample", - kind: "FittableRows", - classes: "gesture-sample enyo-fit enyo-unselectable", - components: [ - { - classes:"gesture-sample-pad", - fit:true, - ondown: "handleEvent", - onup: "handleEvent", - ontap: "handleEvent", - onmove: "handleEvent", - onenter: "handleEvent", - onleave: "handleEvent", - ondragstart: "handleEvent", - ondrag: "handleEvent", - ondragover: "handleEvent", - onhold: "handleEvent", - onrelease: "handleEvent", - onholdpulse: "handleEvent", - onflick: "handleEvent", - ongesturestart: "handleEvent", - ongesturechange: "handleEvent", - ongestureend: "handleEvent", - components: [ - {content: "Perform gestures here"}, - {classes: "gesture-sample-note", content:"(tap below for options)"} - ] - }, - {kind: "onyx.Groupbox", ontap:"toggleSettings", components: [ - {kind: "onyx.GroupboxHeader", content: "Events"}, - {name: "eventList", style:"font-size:12px;", onDone:"removeEvent", components: [ - {name:"waiting", content: "Waiting for events...", style:"padding:4px;font-style:italic;color:gray;"} - ]} - ]}, - {ontap:"toggleSettings", name:"settings", showing:false, components: [ - {kind: "onyx.Groupbox", classes:"gesture-sample-padded", components: [ - {kind: "onyx.GroupboxHeader", content: "Options"}, - {classes:"gesture-sample-setting", components: [ - {content:"Truncate detail on small screen: "}, - {name:"truncateDetail", onchange:"truncateChanged", ontap:"preventDefault", kind:"onyx.Checkbox", checked:true} - ]}, - {classes:"gesture-sample-setting", style:"min-height:40px;", components: [ - {content:"Monitor event: "}, - {kind:"onyx.PickerDecorator", ontap:"preventDefault", onSelect:"monitorEventSelected", components: [ - {content:"Select event", style:"width:140px; margin-bottom:5px;"}, - {name:"eventPicker", kind:"onyx.Picker", classes:"gesture-sample-left"} - ]} - ]} - ]} - ]} - ], - create: function() { - this.inherited(arguments); - this.eventList = {}; - this.eventCount = 0; - enyo.forEach(["All events","down","up","tap","move","enter","leave","dragstart","drag","dragover","hold","release","holdpulse","flick","gesturestart","gesturechange","gestureend"], enyo.bind(this, function(event) { - this.$.eventPicker.createComponent({content:event, style:"text-align:left"}); - })); - }, - handleEvent: function(inSender, inEvent) { - var event = enyo.clone(inEvent); - if (this.monitorEvent && (event.type != this.monitorEvent)) { - return true; - } - var eventItem = this.eventList[event.type]; - if (eventItem) { - eventItem.setEvent(event); - } else { - this.eventCount++; - eventItem = this.$.eventList.createComponent({ - kind: "enyo.sample.EventItem", - event:event, - truncate: this.$.truncateDetail.getValue(), - persist: this.monitorEvent - }); - this.eventList[event.type] = eventItem; - } - eventItem.render(); - this.$.waiting.hide(); - this.reflow(); - return true; - }, - truncateChanged: function() { - for (var i in this.eventList) { - this.eventList[i].setTruncate(this.$.truncateDetail.getValue()); - } - this.reflow(); - return false; - }, - removeEvent: function(inSender, inEvent) { - this.eventCount--; - this.eventList[inEvent.type].destroy(); - delete this.eventList[inEvent.type]; - if (this.eventCount === 0) { - this.$.waiting.show(); - } - this.reflow(); - return true; - }, - removeAllEvents: function() { - for (var i in this.eventList) { - this.eventList[i].destroy(); - delete this.eventList[i]; - } - this.eventCount = 0; - this.$.waiting.show(); - this.reflow(); - }, - toggleSettings: function() { - this.$.settings.setShowing(!this.$.settings.getShowing()); - this.reflow(); - }, - preventDefault: function() { - return true; - }, - monitorEventSelected: function(inSender, inEvent) { - this.removeAllEvents(); - if (inEvent.originator.content == "All events") { - this.monitorEvent = null; - } else { - this.monitorEvent = inEvent.originator.content; - } - } -}); - -enyo.kind({ - name:"enyo.sample.EventItem", - published: { - event:"", - truncate: true, - persist: false - }, - style:"padding:4px;", - events: { - onDone:"" - }, - components: [ - {name:"eventProps", allowHtml:true}, - {kind:"Animator", duration:1000, startValue:0, endValue:255, onStep:"stepAnimation", onEnd:"animationEnded"} - ], - create: function() { - this.inherited(arguments); - this.eventChanged(); - this.truncateChanged(); - }, - truncateChanged: function() { - this.$.eventProps.addRemoveClass("gesture-sample-truncate", this.truncate); - }, - // since event is an object, force set - setEvent: function(inEvent) { - this.setPropertyValue("event", inEvent, "eventChanged"); - }, - eventChanged: function(inOld) { - if (this.event) { - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = null; - } - this.$.animator.stop(); - this.$.eventProps.setContent(this.getPropsString()); - this.$.animator.play(); - } - }, - stepAnimation: function(inSender, inEvent) { - var v = Math.floor(inSender.value); - this.applyStyle("background-color", "rgb(" + v + ",255," + v + ");"); - }, - animationEnded: function() { - if (!this.persist) { - this.timeout = setTimeout(enyo.bind(this, function() { - this.doDone({type:this.event.type}); - }), 2000); - } - }, - destroy: function() { - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = null; - } - this.inherited(arguments); - }, - getPropsString: function() { - var props = []; - for (var i in this.event) { - if ((this.event[i] !== undefined) && - (this.event[i] !== null) && - !(this.event[i] instanceof Object) && - (i != "type")) { - props.push(i + ": " + this.event[i]); - } - } - if (this.event.srcEvent && this.event.srcEvent.type) { - props.push("srcEvent.type: " + this.event.srcEvent.type); - } - return "" + this.event.type + ": { " + props.join(", ") + " }"; - } -}); \ No newline at end of file diff --git a/enyo/samples/JsonpSample.css b/enyo/samples/JsonpSample.css deleted file mode 100644 index 7d9fab8..0000000 --- a/enyo/samples/JsonpSample.css +++ /dev/null @@ -1,14 +0,0 @@ -.jsonp-sample { - padding: 15px; -} - -.jsonp-sample-source { - padding:15px; - font-family: monospace; - font-size: 12px; - white-space: pre-wrap; - box-sizing: border-box; - width:100%; - height:100%; - margin-top:15px; -} diff --git a/enyo/samples/JsonpSample.html b/enyo/samples/JsonpSample.html deleted file mode 100644 index de7e057..0000000 --- a/enyo/samples/JsonpSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - JSON-P Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/JsonpSample.js b/enyo/samples/JsonpSample.js deleted file mode 100644 index b7c8746..0000000 --- a/enyo/samples/JsonpSample.js +++ /dev/null @@ -1,29 +0,0 @@ -enyo.kind({ - name: "enyo.sample.JsonpSample", - kind: "FittableRows", - classes: "enyo-fit jsonp-sample", - components: [ - {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ - {content: "YQL: "}, - {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, - {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} - ]}, - {kind: "onyx.TextArea", fit:true, classes:"jsonp-sample-source"} - ], - fetch: function() { - var jsonp = new enyo.JsonpRequest({ - url: "http://query.yahooapis.com/v1/public/yql?format=json", - callbackName: "callback" - }); - // send parameters the remote service using the 'go()' method - jsonp.go({ - q: this.$.query.getValue() - }); - // attach responders to the transaction object - jsonp.response(this, "processResponse"); - }, - processResponse: function(inSender, inResponse) { - // do something with it - this.$.textArea.setValue(JSON.stringify(inResponse, null, 2)); - } -}); \ No newline at end of file diff --git a/enyo/samples/PlatformSample.css b/enyo/samples/PlatformSample.css deleted file mode 100644 index 326002e..0000000 --- a/enyo/samples/PlatformSample.css +++ /dev/null @@ -1,11 +0,0 @@ -.platform-sample { - padding: 15px; -} -.platform-sample-divider { - color: #F49200; - text-transform: uppercase; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; - font-weight: bold; - margin-bottom: 8px; -} \ No newline at end of file diff --git a/enyo/samples/PlatformSample.html b/enyo/samples/PlatformSample.html deleted file mode 100644 index e06115f..0000000 --- a/enyo/samples/PlatformSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Platform Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/PlatformSample.js b/enyo/samples/PlatformSample.js deleted file mode 100644 index 389e6e9..0000000 --- a/enyo/samples/PlatformSample.js +++ /dev/null @@ -1,36 +0,0 @@ -enyo.kind({ - name: "enyo.sample.PlatformSample", - kind: "FittableRows", - classes: "enyo-fit platform-sample", - components: [ - {classes: "platform-sample-divider", content: "Enyo Platform Detection"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "User-Agent String"}, - {name: "uaString", content: "", style: "padding: 8px;"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "Window"}, - {name: "windowAttr", content: "", style: "padding: 8px;"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "enyo.platform"}, - {name: "enyoPlatformJSON", content: "", style: "padding: 8px;"} - ]} - ], - updateWindowSize: function() { - this.$.windowAttr.setContent("size: " + window.innerWidth + "x" + window.innerHeight + - ", devicePixelRatio: " + window.devicePixelRatio); - }, - create: function() { - this.inherited(arguments); - this.$.uaString.setContent(navigator.userAgent); - this.$.enyoPlatformJSON.setContent(JSON.stringify(enyo.platform, null, 1)); - this.updateWindowSize(); - }, - resizeHandler: function() { - this.inherited(arguments); - this.updateWindowSize(); - } -}); \ No newline at end of file diff --git a/enyo/samples/Playground.css b/enyo/samples/Playground.css deleted file mode 100644 index bc8b4fd..0000000 --- a/enyo/samples/Playground.css +++ /dev/null @@ -1,29 +0,0 @@ -.playground-sample-player { - padding: 15px; -} - -.playground-sample-source { - padding:15px; - font-family: monospace; - font-size: 12px; - white-space: pre-wrap; - box-sizing: border-box; - width:100%; - height:100%; -} - -.playground-sample-panels > * { - width:320px; - box-shadow: -4px 0px 4px rgba(0,0,0,0.3); - -moz-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); - -webkit-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); -} - -.sample-output { - min-height: 200px; - border: 1px solid black; - margin: 10px; - padding: 10px; - border-radius: 10px; - text-align: center; -} diff --git a/enyo/samples/Playground.html b/enyo/samples/Playground.html deleted file mode 100644 index fb6b7a8..0000000 --- a/enyo/samples/Playground.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - Enyo Playground - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/Playground.js b/enyo/samples/Playground.js deleted file mode 100644 index 970a0dc..0000000 --- a/enyo/samples/Playground.js +++ /dev/null @@ -1,54 +0,0 @@ -enyo.kind({ - name: "enyo.sample.Playground", - kind: "Panels", - classes: "enyo-fit onyx playground-sample-panels", - arrangerKind:"CollapsingArranger", - components: [ - {kind: "FittableRows", style:"width:50%;", components: [ - {kind: "onyx.Toolbar", name:"toolbar", layoutKind:"FittableColumnsLayout", components: [ - {content: "Enyo Playground", fit:true}, - {kind: "onyx.PickerDecorator", components: [ - {}, - {kind: "onyx.Picker", floating:true, onChange:"sampleChanged", components: [ - {content:"Sample1", active:true}, - {content:"Sample2"}, - {content:"Sample3"}, - {content:"Sample4"} - ]} - ]} - ]}, - {fit:true, style:"padding:15px;", components: [ - {kind: "CodeEditor", fit:true, classes:"playground-sample-source"}, - ]}, - {kind: "FittableColumns", style:"margin:0px 15px 15px 15px", components: [ - {fit:true}, // spacer - {kind: "onyx.Button", content: "Render Kind", ontap: "go"} - ]} - ]}, - {kind: "FittableRows", classes:"onyx", components: [ - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Grabber"}, - {content: "Result"} - ]}, - {kind: "Scroller", fit:true, components: [ - {kind: "CodePlayer", fit:true, classes: "playground-sample-player"} - ]} - ]} - ], - create: function() { - this.inherited(arguments); - }, - sampleChanged: function(inSender, inEvent) { - this.loadSample(inEvent.selected.content); - this.$.toolbar.resized(); - }, - loadSample: function(inSample) { - this.$.codeEditor.setUrl("assets/" + inSample + ".js"); - }, - go: function() { - this.$.codePlayer.go(this.$.codeEditor.getValue()); - if (enyo.Panels.isScreenNarrow()) { - this.next(); - } - } -}); \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.css b/enyo/samples/RepeaterSample.css deleted file mode 100644 index 09ff891..0000000 --- a/enyo/samples/RepeaterSample.css +++ /dev/null @@ -1,9 +0,0 @@ -.repeater-sample { - padding:15px; -} -.repeater-sample-item { - padding:4px; - margin:2px; - border:1px solid gray; - background-color: lightgray; -} \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.html b/enyo/samples/RepeaterSample.html deleted file mode 100644 index 28d0328..0000000 --- a/enyo/samples/RepeaterSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Repeater Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/RepeaterSample.js b/enyo/samples/RepeaterSample.js deleted file mode 100644 index 732c45e..0000000 --- a/enyo/samples/RepeaterSample.js +++ /dev/null @@ -1,52 +0,0 @@ -enyo.kind({ - name: "enyo.sample.RepeaterSample", - classes: "enyo-fit repeater-sample", - components: [ - {kind: "Repeater", onSetupItem:"setupItem", components: [ - {name:"item", classes:"repeater-sample-item", components: [ - {tag:"span", name: "personNumber"}, - {tag:"span", name: "personName"} - ]} - ]} - ], - create: function() { - this.inherited(arguments); - this.$.repeater.setCount(this.people.length); - }, - setupItem: function(inSender, inEvent) { - var index = inEvent.index; - var item = inEvent.item; - var person = this.people[index]; - item.$.personNumber.setContent((index+1) + ". "); - item.$.personName.setContent(person.name); - item.$.personName.applyStyle("color", person.sex == "male" ? "dodgerblue" : "deeppink"); - }, - people: [ - {name: "Andrew", sex:"male"}, - {name: "Betty", sex:"female"}, - {name: "Christopher", sex:"male"}, - {name: "Donna", sex:"female"}, - {name: "Ephraim", sex:"male"}, - {name: "Frankie", sex:"male"}, - {name: "Gerald", sex:"male"}, - {name: "Heather", sex:"female"}, - {name: "Ingred", sex:"female"}, - {name: "Jack", sex:"male"}, - {name: "Kevin", sex:"male"}, - {name: "Lucy", sex:"female"}, - {name: "Matthew", sex:"male"}, - {name: "Noreen", sex:"female"}, - {name: "Oscar", sex:"male"}, - {name: "Pedro", sex:"male"}, - {name: "Quentin", sex:"male"}, - {name: "Ralph", sex:"male"}, - {name: "Steven", sex:"male"}, - {name: "Tracy", sex:"female"}, - {name: "Uma", sex:"female"}, - {name: "Victor", sex:"male"}, - {name: "Wendy", sex:"female"}, - {name: "Xin", sex:"male"}, - {name: "Yulia", sex:"female"}, - {name: "Zoltan"} - ] -}); \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.css b/enyo/samples/ScrollerSample.css deleted file mode 100644 index fef4aa7..0000000 --- a/enyo/samples/ScrollerSample.css +++ /dev/null @@ -1,9 +0,0 @@ -.scroller-sample-panels { - margin:15px; -} -.scroller-sample-content { - width:4000px; -} -.scroller-sample-scroller { - border: 1px solid orange; -} \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.html b/enyo/samples/ScrollerSample.html deleted file mode 100644 index 2360c11..0000000 --- a/enyo/samples/ScrollerSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Scroller Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/ScrollerSample.js b/enyo/samples/ScrollerSample.js deleted file mode 100644 index b488d8a..0000000 --- a/enyo/samples/ScrollerSample.js +++ /dev/null @@ -1,78 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ScrollerSample", - kind: "FittableRows", - classes: "enyo-fit enyo-unselectable", - components: [ - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.PickerDecorator", components: [ - {content:"Choose Scroller", style:"width:250px;"}, - {kind: "onyx.Picker", floating:true, maxHeight: 300, onSelect:"sampleChanged", components: [ - {content:"Default scroller", active:true}, - {content:"Force touch scroller"}, - {content:"Horizontal only"}, - {content:"Vertical only"}, - {content:"Force TouchScrollStrategy"}, - {content:"Force TransitionScrollStrategy"}, - {content:"Force TranslateScrollStrategy"} - ]} - ]} - ]}, - {kind: "Panels", fit: true, draggable: false, classes: "scroller-sample-panels", components: [ - // Default scroller (chooses best scrolling method for platform) - {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit"}, - // Forces touch scrolling, even on desktop - {kind: "Scroller", touch:true, classes: "scroller-sample-scroller enyo-fit"}, - // Horizontal-only scrolling - {kind: "Scroller", vertical:"hidden", classes: "scroller-sample-scroller enyo-fit"}, - // Vertical-only scrolling - {kind: "Scroller", horizontal:"hidden", classes: "scroller-sample-scroller enyo-fit", onmousedown: "mouseDown", ondragstart: "dragStart"}, - // Force specific strategies - {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TouchScrollStrategy"}, - {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TransitionScrollStrategy"}, - {kind: "Scroller", classes: "scroller-sample-scroller enyo-fit", strategyKind: "TranslateScrollStrategy"} - ]} - ], - create: function() { - this.inherited(arguments); - var scrollers = this.$.panels.getPanels(); - for (var i in scrollers) { - scrollers[i].createComponent({ - allowHtml:true, - content:this.text, - classes:"scroller-sample-content" - }); - } - }, - sampleChanged: function(inSender, inEvent) { - this.$.panels.setIndex(inEvent.selected.indexInContainer()-1); - }, - text: "Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + - "Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow.
    Foo
    Bar
    Bar
    " + - "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + - "Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow.
    Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    " + - "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    " + - "Foo
    Bar
    Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow.
    Foo
    Bar
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    " + - "Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow
    Foo
    Bar
    Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. " + - "Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow.
    ", - // The following are used when this sample is called from the Sampler app - mouseDown: function(inSender, inEvent) { - inEvent.preventDefault(); - }, - dragStart: function(inSender, inEvent) { - if (inEvent.horizontal) { - // Prevent drag propagation on horizontal drag events - return true; - } - } -}); \ No newline at end of file diff --git a/enyo/samples/WebServiceSample.css b/enyo/samples/WebServiceSample.css deleted file mode 100644 index d63e5ba..0000000 --- a/enyo/samples/WebServiceSample.css +++ /dev/null @@ -1,14 +0,0 @@ -.webservice-sample { - padding: 15px; -} - -.webservice-sample-source { - padding:15px; - font-family: monospace; - font-size: 12px; - white-space: pre-wrap; - box-sizing: border-box; - width:100%; - height:100%; - margin-top:15px; -} diff --git a/enyo/samples/WebServiceSample.html b/enyo/samples/WebServiceSample.html deleted file mode 100644 index 10dbdc3..0000000 --- a/enyo/samples/WebServiceSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - WebService Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/enyo/samples/WebServiceSample.js b/enyo/samples/WebServiceSample.js deleted file mode 100644 index 78b0f31..0000000 --- a/enyo/samples/WebServiceSample.js +++ /dev/null @@ -1,32 +0,0 @@ -enyo.kind({ - name: "enyo.sample.WebServiceSample", - kind: "FittableRows", - classes: "enyo-fit webservice-sample", - components: [ - {kind: "WebService", name:"yql", url: "http://query.yahooapis.com/v1/public/yql?format=json", onResponse:"processResponse", callbackName: "callback"}, - {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [ - {content: "YQL: "}, - {kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'}, - {kind: "onyx.PickerDecorator", components: [ - {content:"Choose Scroller", style:"width:100px;"}, - {kind: "onyx.Picker", floating:true, components: [ - {content:"AJAX", active:true}, - {content:"JSON-P"} - ]} - ]}, - {kind: "onyx.Button", content:"Fetch", ontap:"fetch"} - ]}, - {kind: "onyx.TextArea", fit:true, classes:"webservice-sample-source"} - ], - fetch: function() { - // send parameters the remote service using the 'send()' method - this.$.yql.send({ - q: this.$.query.getValue(), - jsonp: (this.$.picker.getSelected().indexInContainer()==2) - }); - }, - processResponse: function(inSender, inEvent) { - // do something with it - this.$.textArea.setValue(JSON.stringify(inEvent.data, null, 2)); - } -}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample1.js b/enyo/samples/assets/Sample1.js deleted file mode 100644 index 1b34875..0000000 --- a/enyo/samples/assets/Sample1.js +++ /dev/null @@ -1,15 +0,0 @@ -enyo.kind({ - name: "Sample", - kind: "Control", - components: [ - {name: "input", tag: "input"}, - {tag: "br"}, - {name: "button", tag: "button", content: "Set Content", ontap: "buttonTap"}, - {tag: "br"}, - {name: "output", classes: "sample-output"} - ], - buttonTap: function(inSender, inEvent) { - var value = this.$.input.hasNode().value; - this.$.output.setContent(value); - } -}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample2.js b/enyo/samples/assets/Sample2.js deleted file mode 100644 index 04fe5ab..0000000 --- a/enyo/samples/assets/Sample2.js +++ /dev/null @@ -1,15 +0,0 @@ -enyo.kind({ - name: "Sample", - kind: "Control", - components: [ - {name: "input", tag: "input", attributes: {value: "red"}}, - {tag: "br"}, - {tag: "button", content: "Set Color", ontap: "buttonTap"}, - {tag: "br"}, - {name: "output", classes: "sample-output"} - ], - buttonTap: function(inSender, inEvent) { - var color = this.$.input.hasNode().value; - this.$.output.applyStyle("background", color); - } -}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample3.js b/enyo/samples/assets/Sample3.js deleted file mode 100644 index ee0b9ef..0000000 --- a/enyo/samples/assets/Sample3.js +++ /dev/null @@ -1,30 +0,0 @@ -enyo.kind({ - name: "Sample", - kind: "Control", - components: [ - {name: "input", tag: "input", attributes: {value: "Foo "}}, - {tag: "br"}, - {tag: "button", content: "Add Content", ontap: "addContentTap"}, - {tag: "br"}, - {tag: "button", style: "margin-right: .5em;", content: "Hide", ontap: "hideTap"}, - {tag: "button", style: "margin-right: .5em;", content: "Show", ontap: "showTap"}, - {tag: "button", content: "Toggle class", ontap: "toggleClassTap"}, - {tag: "br"}, - {name: "output", classes: "sample-output"} - ], - addContentTap: function(inSender, inEvent) { - var content = this.$.input.hasNode().value; - this.$.output.addContent(content); - }, - hideTap: function(inSender, inEvent) { - this.$.output.hide(); - }, - showTap: function(inSender, inEvent) { - this.$.output.show(); - }, - toggleClassTap: function(inSender, inEvent) { - var c = "sample-output"; - var has = this.$.output.hasClass(c); - this.$.output.addRemoveClass(c, !has); - } -}); \ No newline at end of file diff --git a/enyo/samples/assets/Sample4.js b/enyo/samples/assets/Sample4.js deleted file mode 100644 index cc2de00..0000000 --- a/enyo/samples/assets/Sample4.js +++ /dev/null @@ -1,24 +0,0 @@ -enyo.kind({ - name: "Sample", - kind: "Control", - components: [ - {content: "Create a button control with the given content:", style: "padding: 10px 0;"}, - {name: "input", tag: "input", attributes: {value: "Foo"}, style: "display: block;"}, - {style: "padding: 10px 0;", components: [ - {tag: "button", style: "margin-right: 10px;", content: "Add", ontap: "addTap"}, - {tag: "button", content: "Clear", ontap: "clearTap"}, - ]}, - {name: "output"} - ], - addTap: function(inSender, inEvent) { - var content = this.$.input.hasNode().value; - this.createComponent({ - tag: "button", - content: content, - container: this.$.output - }).render(); - }, - clearTap: function(inSender, inEvent) { - this.$.output.destroyClientControls(); - } -}); \ No newline at end of file diff --git a/enyo/samples/package.js b/enyo/samples/package.js deleted file mode 100644 index e6972c3..0000000 --- a/enyo/samples/package.js +++ /dev/null @@ -1,19 +0,0 @@ -enyo.depends( - "$lib/extra/exampler", - "PlatformSample.css", - "PlatformSample.js", - "Playground.css", - "Playground.js", - "AjaxSample.css", - "AjaxSample.js", - "JsonpSample.css", - "JsonpSample.js", - "WebServiceSample.css", - "WebServiceSample.js", - "RepeaterSample.css", - "RepeaterSample.js", - "ScrollerSample.css", - "ScrollerSample.js", - "GestureSample.css", - "GestureSample.js" -); \ No newline at end of file diff --git a/enyo/source/ajax/Ajax.js b/enyo/source/ajax/Ajax.js deleted file mode 100644 index 7869f10..0000000 --- a/enyo/source/ajax/Ajax.js +++ /dev/null @@ -1,255 +0,0 @@ -/** - _enyo.Ajax_ is a wrapper for _XmlHttpRequest_ that uses - the enyo.Async API. - - _enyo.Ajax_ publishes all the properties of the - enyo.AjaxProperties - object. - - Like _enyo.Async_, _enyo.Ajax_ is an **Object**, not a **Component**. - Do not try to make _enyo.Ajax_ objects inside a _components_ block. - If you want to use _enyo.Ajax_ as a component, you should probably - be using enyo.WebService instead. - - If you make changes to _enyo.Ajax_, be sure to add or update the appropriate - [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). - - For more information, see the documentation on - [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Ajax", - kind: enyo.Async, - //* See enyo.AjaxProperties for the list of properties - //* published by _enyo.Ajax_. - published: enyo.AjaxProperties, - //* @protected - constructor: function(inParams) { - enyo.mixin(this, inParams); - this.inherited(arguments); - }, - //* @public - /** - Sends the Ajax request with parameters _inParams_. _inParams_ values may be - either Strings or Objects. - - _inParams_ as an Object is converted into the url query string. For - instance, passing {q: "searchTerm"} will result in the addition - of the string `q="searchTerm"` to the current url query string. - - _inParams_ as a String is used as the query part of the URL directly. - - _inParams_ will not be converted into a POST body, it will always be used as - part of the URL query string if provided. Use the `postBody` property for - specifying a body. - - When the request is completed, the code will set a `xhrResponse` property - in the `enyo.Ajax` object with the subproperties `status`, `headers`, and - `body`. These cache the results from the XHR for later use. The keys for - the `headers` object have been converted to all lower case as HTTP headers - are case-insensitive. - */ - go: function(inParams) { - this.startTimer(); - this.request(inParams); - return this; - }, - //* @protected - request: function(inParams) { - var parts = this.url.split("?"); - var uri = parts.shift() || ""; - var args = parts.length ? (parts.join("?").split("&")) : []; - // - var query = null; - // - if(enyo.isString(inParams)){ - //If inParams parameter is a string, use it as request body - query = inParams; - } - else{ - //If inParams parameter is not a string, build a query from it - if(inParams){ - query = enyo.Ajax.objectToQuery(inParams); - } - } - // - if (query) { - args.push(query); - query = null; - } - if (this.cacheBust) { - args.push(Math.random()); - } - // - var url = args.length ? [uri, args.join("&")].join("?") : uri; - // - var xhr_headers = {}; - var body; - if (this.method != "GET") { - body = this.postBody; - if (this.method === "POST" && body instanceof enyo.FormData) { - if (body.fake) { - xhr_headers["Content-Type"] = body.getContentType(); - body = body.toString(); - } else { - // Nothing to do as the - // content-type will be - // automagically set according - // to the FormData - } - } else { - xhr_headers["Content-Type"] = this.contentType; - if (body instanceof Object) { - if (this.contentType === "application/json") { - body = JSON.stringify(body); - } else if (this.contentType === "application/x-www-form-urlencoded") { - body = enyo.Ajax.objectToQuery(body); - } - else { - body = body.toString(); - } - } - } - } - enyo.mixin(xhr_headers, this.headers); - // don't pass in headers structure if there are no headers defined as this messes - // up CORS code for IE8-9 - if (enyo.keys(xhr_headers).length === 0) { - xhr_headers = undefined; - } - // - try { - this.xhr = enyo.xhr.request({ - url: url, - method: this.method, - callback: enyo.bind(this, "receive"), - body: body, - headers: xhr_headers, - sync: window.PalmSystem ? false : this.sync, - username: this.username, - password: this.password, - xhrFields: this.xhrFields, - mimeType: this.mimeType - }); - } - catch (e) { - // IE can throw errors here if the XHR would fail CORS checks, - // so catch and turn into a failure. - this.fail(e); - } - }, - receive: function(inText, inXhr) { - if (!this.failed && !this.destroyed) { - var body; - if (typeof inXhr.responseText === "string") { - body = inXhr.responseText; - } else { - // IE carrying a binary - body = inXhr.responseBody; - } - this.xhrResponse = { - status: inXhr.status, - headers: enyo.Ajax.parseResponseHeaders(inXhr), - body: body - }; - if (this.isFailure(inXhr)) { - this.fail(inXhr.status); - } else { - this.respond(this.xhrToResponse(inXhr)); - } - } - }, - fail: function(inError) { - // on failure, explicitly cancel the XHR to prevent - // further responses. cancellation also resets the - // response headers & body, - if (this.xhr) { - enyo.xhr.cancel(this.xhr); - this.xhr = null; - } - this.inherited(arguments); - }, - xhrToResponse: function(inXhr) { - if (inXhr) { - return this[(this.handleAs || "text") + "Handler"](inXhr); - } - }, - isFailure: function(inXhr) { - // if any exceptions are thrown while checking fields in the xhr, - // assume a failure. - try { - var text = ""; - // work around IE8-9 bug where accessing responseText will thrown error - // for binary requests. - if (typeof inXhr.responseText === "string") { - text = inXhr.responseText; - } - // Follow same failure policy as jQuery's Ajax code - // CORS failures on FireFox will have status 0 and no responseText, - // so treat that as failure. - if (inXhr.status === 0 && text === "") { - return true; - } - // Otherwise, status 0 may be good for local file access. We treat the range - // 1-199 and 300+ as failure (only 200-series code are OK). - return (inXhr.status !== 0) && (inXhr.status < 200 || inXhr.status >= 300); - } - catch (e) { - return true; - } - }, - xmlHandler: function(inXhr) { - return inXhr.responseXML; - }, - textHandler: function(inXhr) { - return inXhr.responseText; - }, - jsonHandler: function(inXhr) { - var r = inXhr.responseText; - try { - return r && enyo.json.parse(r); - } catch (x) { - enyo.warn("Ajax request set to handleAs JSON but data was not in JSON format"); - return r; - } - }, - statics: { - objectToQuery: function(/*Object*/ map) { - var enc = encodeURIComponent; - var pairs = []; - var backstop = {}; - for (var name in map){ - var value = map[name]; - if (value != backstop[name]) { - var assign = enc(name) + "="; - if (enyo.isArray(value)) { - for (var i=0; i < value.length; i++) { - pairs.push(assign + enc(value[i])); - } - } else { - pairs.push(assign + enc(value)); - } - } - } - return pairs.join("&"); - }, - parseResponseHeaders: function(xhr) { - var headers = {}; - var headersStr = []; - if (xhr.getAllResponseHeaders) { - headersStr = xhr.getAllResponseHeaders().split(/\r?\n/); - } - for (var i = 0; i < headersStr.length; i++) { - var headerStr = headersStr[i]; - var index = headerStr.indexOf(': '); - if (index > 0) { - var key = headerStr.substring(0, index).toLowerCase(); - var val = headerStr.substring(index + 2); - headers[key] = val; - } - } - return headers; - } - } -}); diff --git a/enyo/source/ajax/AjaxProperties.js b/enyo/source/ajax/AjaxProperties.js deleted file mode 100644 index bcd7405..0000000 --- a/enyo/source/ajax/AjaxProperties.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - Common set of published properties used in both - enyo.Ajax and - enyo.WebService. -*/ -enyo.AjaxProperties = { - /** - When true, appends a random number as a parameter for GET requests - to try to force a new fetch of the resource instead of reusing a local cache. - */ - cacheBust: true, - /** - The URL for the service. This can be a relative URL if used to fetch resources bundled with the application. - */ - url: "", - /** - The HTTP method to use for the request, defaults to GET. Supported values include - "GET", "POST", "PUT", and "DELETE". - */ - method: "GET", // {value: "GET", options: ["GET", "POST", "PUT", "DELETE"]}, - /** - How the response will be handled. - Supported values are: "json", "text", "xml" - */ - handleAs: "json", // {value: "json", options: ["text", "json", "xml"]}, - /** - The Content-Type header for the request as a String. - */ - contentType: "application/x-www-form-urlencoded", - /** - If true, makes a synchronous (blocking) call, if supported. Synchronous requests - are not supported on HP webOS. - */ - sync: false, - /** - Optional additional request headers as a JS object, e.g. - { "X-My-Header": "My Value", "Mood": "Happy" } or null. - */ - headers: null, - /** - The content for the request body for POST/PUT methods. - - When postBody is a Buffer or a String, it is passed verbatim in the request body. - When postBody is an Object, the way it is encoded depends on the contentType: - - * application/json => JSON.stringify - * application/x-www-urlencoed => url-encoded parameters - * multipart/form-data => passed as fields in enyo.FormData (XHR2 emulation) - */ - postBody: "", - /** - The optional user name to use for authentication purposes. - */ - username: "", - /** - The optional password to use for authentication purposes. - */ - password: "", - /** - Optional object with fields to pass directly to the underlying XHR object. - One example is the _withCredentials_ flag used for cross-origin requests. - */ - xhrFields: null, - /** - Optional string to override the MIME-Type header. - */ - mimeType: null -}; diff --git a/enyo/source/ajax/Async.js b/enyo/source/ajax/Async.js deleted file mode 100644 index 6a2fb9f..0000000 --- a/enyo/source/ajax/Async.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - _enyo.Async_ is the base kind for handling asynchronous operations. - - _enyo.Async_ is an **Object**, not a **Component**; thus, you may not declare - an _Async_ in a _components_ block. If you want to use _Async_ as a - component, you should probably be using - enyo.WebService instead. - - An Async object represents a task that has not yet completed. You may attach - callback functions to an Async, to be called when the task completes or - encounters an error. - - More information on _Async_ and its usage is available in the documentation on - Consuming Web Services - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Async", - kind: enyo.Object, - published: { - /** - If set to a non-zero value, the number of milliseconds to - wait after the _go_ call before failing with the "timeout" error - */ - timeout: 0 - }, - //* @protected - failed: false, - context: null, - constructor: function() { - this.responders = []; - this.errorHandlers = []; - }, - accumulate: function(inArray, inMethodArgs) { - var fn = (inMethodArgs.length < 2) ? inMethodArgs[0] : enyo.bind(inMethodArgs[0], inMethodArgs[1]); - inArray.push(fn); - }, - //* @public - /** - Registers a response function. - First parameter is an optional _this_ context for the response method. - Second (or only) parameter is the function object. - */ - response: function(/* [inContext], inResponder */) { - this.accumulate(this.responders, arguments); - return this; - }, - /** - Registers an error handler. - First parameter is an optional _this_ context for the response method. - Second (or only) parameter is the function object. - */ - error: function(/* [inContext], inResponder */) { - this.accumulate(this.errorHandlers, arguments); - return this; - }, - //* @protected - route: function(inAsync, inValue) { - var r = enyo.bind(this, "respond"); - inAsync.response(function(inSender, inValue) { - r(inValue); - }); - var f = enyo.bind(this, "fail"); - inAsync.error(function(inSender, inValue) { - f(inValue); - }); - inAsync.go(inValue); - }, - handle: function(inValue, inHandlers) { - var r = inHandlers.shift(); - if (r) { - if (r instanceof enyo.Async) { - this.route(r, inValue); - } else { - // handler can return a new 'value' - var v = enyo.call(this.context || this, r, [this, inValue]); - // ... but only if it returns something other than undefined - v = (v !== undefined) ? v : inValue; - // next handler - (this.failed ? this.fail : this.respond).call(this, v); - } - } - }, - startTimer: function() { - this.startTime = enyo.now(); - if (this.timeout) { - this.timeoutJob = setTimeout(enyo.bind(this, "timeoutComplete"), this.timeout); - } - }, - endTimer: function() { - if (this.timeoutJob) { - this.endTime = enyo.now(); - clearTimeout(this.timeoutJob); - this.timeoutJob = null; - this.latency = this.endTime - this.startTime; - } - }, - timeoutComplete: function() { - this.timedout = true; - this.fail("timeout"); - }, - //* @protected - //* Called as part of the async implementation; triggers the handler chain. - respond: function(inValue) { - this.failed = false; - this.endTimer(); - this.handle(inValue, this.responders); - }, - //* @public - //* Can be called from any handler to trigger the error chain. - fail: function(inError) { - this.failed = true; - this.endTimer(); - this.handle(inError, this.errorHandlers); - }, - //* Called from an error handler; clears the error condition and resumes - //* calling handler methods. - recover: function() { - this.failed = false; - }, - //* Starts the async activity. Overridden in subkinds. - go: function(inValue) { - enyo.asyncMethod(this, function() { - this.respond(inValue); - }); - return this; - } -}); diff --git a/enyo/source/ajax/Jsonp.js b/enyo/source/ajax/Jsonp.js deleted file mode 100644 index 2e6463a..0000000 --- a/enyo/source/ajax/Jsonp.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - _enyo.JsonpRequest_ is a specialized form of - enyo.Async used for making JSONP requests to a - remote server. This differs from the normal XmlHTTPRequest call in that the - external resource is loaded using a <script> tag. This allows us to - bypass the same-domain rules that normally apply to XHR, since the browser - will load scripts from any address. - - If you make changes to _enyo.JsonpRequest_, be sure to add or update the - appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). - - For more information, see the documentation on - [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.JsonpRequest", - kind: enyo.Async, - published: { - //* The URL for the service - url: "", - //* Optional character set to use to interpret the return data - charset: null, - /** - Name of the argument that holds the callback name. For example, the - Twitter search API uses "callback" as the parameter to hold the - name of the called function. We will automatically add this to - the encoded arguments. - */ - callbackName: "callback", - /** - When true, appends a random number as a parameter for GET requests - to try to force a new fetch of the resource instead of reusing a - local cache - */ - cacheBust: true - }, - statics: { - // Counter to allow creation of unique name for each JSONP request - nextCallbackID: 0 - }, - //* @protected - addScriptElement: function() { - var script = document.createElement('script'); - script.src = this.src; - script.async = "async"; - if (this.charset) { - script.charset = this.charset; - } - // most modern browsers also have an onerror handler - script.onerror = enyo.bind(this, function() { - // we don't get an error code, so we'll just use the generic 400 error status - this.fail(400); - }); - // add script before existing script to make sure it's in a valid part of document - // http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ - var first = document.getElementsByTagName('script')[0]; - first.parentNode.insertBefore(script, first); - this.scriptTag = script; - }, - removeScriptElement: function() { - var script = this.scriptTag; - this.scriptTag = null; - script.onerror = null; - if (script.parentNode) { - script.parentNode.removeChild(script); - } - }, - constructor: function(inParams) { - enyo.mixin(this, inParams); - this.inherited(arguments); - }, - //* @public - //* Starts the JSONP request. - go: function(inParams) { - this.startTimer(); - this.jsonp(inParams); - return this; - }, - //* @protected - jsonp: function(inParams) { - var callbackFunctionName = "enyo_jsonp_callback_" + (enyo.JsonpRequest.nextCallbackID++); - // - this.src = this.buildUrl(inParams, callbackFunctionName); - this.addScriptElement(); - // - window[callbackFunctionName] = enyo.bind(this, this.respond); - // - // setup cleanup handlers for JSONP completion and failure - var cleanup = enyo.bind(this, function() { - this.removeScriptElement(); - window[callbackFunctionName] = null; - }); - this.response(cleanup); - this.error(cleanup); - }, - buildUrl: function(inParams, inCallbackFunctionName) { - var parts = this.url.split("?"); - var uri = parts.shift() || ""; - var args = parts.join("?").split("&"); - // - var bodyArgs = this.bodyArgsFromParams(inParams, inCallbackFunctionName); - args.push(bodyArgs); - if (this.cacheBust) { - args.push(Math.random()); - } - // - return [uri, args.join("&")].join("?"); - }, - // for a string version of inParams, we follow the convention of - // replacing the string "=?" with the callback name. For the more - // common case of inParams being an object, we'll add a argument named - // using the callbackName published property. - bodyArgsFromParams: function(inParams, inCallbackFunctionName) { - if (enyo.isString(inParams)) { - return inParams.replace("=?", "=" + inCallbackFunctionName); - } else { - var params = enyo.mixin({}, inParams); - params[this.callbackName] = inCallbackFunctionName; - return enyo.Ajax.objectToQuery(params); - } - } -}); \ No newline at end of file diff --git a/enyo/source/ajax/WebService.js b/enyo/source/ajax/WebService.js deleted file mode 100644 index 337b254..0000000 --- a/enyo/source/ajax/WebService.js +++ /dev/null @@ -1,114 +0,0 @@ -//* @protected -enyo.kind({ - name: "enyo._AjaxComponent", - kind: enyo.Component, - published: enyo.AjaxProperties -}); - -//* @public -/** - _enyo.WebService_ is a component that performs Web requests (_XmlHttpRequest_). - - Internally, _enyo.WebService_ uses _enyo.Async_ subkinds (namely, - enyo.Ajax and - enyo.JsonpRequest) to manage transactions. - The _send_ method returns the Async instance used by the request. - - _enyo.WebService_ uses _enyo.Ajax_ by default and, like _enyo.Ajax_, it - publishes all the properties of the - enyo.AjaxProperties object. - - To use `enyo.JsonpRequest` instead of `enyo.Ajax`, set `json` to `true`. - - If you make changes to _enyo.WebService_, be sure to add or update the - appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). - - For more information, see the documentation on - [Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.WebService", - kind: enyo._AjaxComponent, - published: { - //* Set to true to use JSONP protocol - jsonp: false, - /** - When using JSONP, the name of the callback parameter. - Note that this not the name of a callback function, but only - the name of the callback parameter. Enyo will create an - internal callback function as necessary. - */ - callbackName: "callback", - /** - When using JSONP, optional character set to use to interpret the - return data - */ - charset: null, - /** - If set to a non-zero value, the number of milliseconds to - wait after the _send_ call before failing with a "timeout" error - */ - timeout: 0 - }, - events: { - /** - Fires when a response is received. - - _inEvent.ajax_ contains the Async instance associated with the request. - - _inEvent.data_ contains the response data. - */ - onResponse: "", - /** - Fires when an error is received. - - _inEvent.ajax_ contains the Async instance associated with the request. - - _inEvent.data_ contains the error data. - */ - onError: "" - }, - //* @protected - constructor: function(inProps) { - this.inherited(arguments); - }, - //* @public - /** - Sends a Web request with the passed-in parameters, returning the - associated Async instance. - - _inProps_ is an optional object parameterthat can be used to override some - of the AJAX properties for this request, such as setting a _postBody_. - */ - send: function(inParams, inProps) { - return this.jsonp ? this.sendJsonp(inParams, inProps) : this.sendAjax(inParams, inProps); - }, - //* @protected - sendJsonp: function(inParams, inProps) { - var jsonp = new enyo.JsonpRequest(); - for (var n in {'url':1, 'callbackName':1, 'charset':1, 'timeout':1}) { - jsonp[n] = this[n]; - } - enyo.mixin(jsonp, inProps); - return this.sendAsync(jsonp, inParams); - }, - sendAjax: function(inParams, inProps) { - var ajax = new enyo.Ajax(inProps); - for (var n in enyo.AjaxProperties) { - ajax[n] = this[n]; - } - ajax.timeout = this.timeout; - enyo.mixin(ajax, inProps); - return this.sendAsync(ajax, inParams); - }, - sendAsync: function(inAjax, inParams) { - return inAjax.go(inParams).response(this, "response").error(this, "error"); - }, - response: function(inSender, inData) { - this.doResponse({ajax: inSender, data: inData}); - }, - error: function(inSender, inData) { - this.doError({ajax: inSender, data: inData}); - } -}); diff --git a/enyo/source/ajax/cookie.js b/enyo/source/ajax/cookie.js deleted file mode 100644 index c76e1aa..0000000 --- a/enyo/source/ajax/cookie.js +++ /dev/null @@ -1,50 +0,0 @@ -//* @public - -/** - Gets a named value from the document cookie. -*/ -enyo.getCookie = function(inName) { - var matches = document.cookie.match(new RegExp("(?:^|; )" + inName + "=([^;]*)")); - return matches ? decodeURIComponent(matches[1]) : undefined; -}; - -/** - Sets a named value in the document cookie, with properties. - - Properties in the optional _inProps_ argument are attached to the cookie. - _inProps_ may have an _expires_ property, which can be a number of days, a - Date object, or a UTC time string. - - To remove a cookie, use an _inProps_ value of { "Max-Age": 0 }. - - If developing in the Google Chrome browser with a local file as your - application, start Chrome with the --enable-file-cookies switch - to allow cookies to be set. -*/ -enyo.setCookie = function(inName, inValue, inProps) { - var cookie = inName + "=" + encodeURIComponent(inValue); - var p = inProps || {}; - // - // FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs? - var exp = p.expires; - if (typeof exp == "number") { - var d = new Date(); - d.setTime(d.getTime() + exp*24*60*60*1000); - exp = d; - } - if (exp && exp.toUTCString) { - p.expires = exp.toUTCString(); - } - // - var name, value; - for (name in p){ - cookie += "; " + name; - value = p[name]; - if (value !== true) { - cookie += "=" + value; - } - } - // - //enyo.log(cookie); - document.cookie = cookie; -}; diff --git a/enyo/source/ajax/formdata.js b/enyo/source/ajax/formdata.js deleted file mode 100644 index 1d47188..0000000 --- a/enyo/source/ajax/formdata.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - -_enyo.FormData_ is an [XHR2](http://www.w3.org/TR/XMLHttpRequest/) -`FormData` implementation. It is used to send `multipart/form-data` -Ajax requests. _enyo.Blob_ is the associated content provider for -file-parts. - -Note that in IE<10, both _enyo.FormData_ and _enyo.Blob_ are limited -to `String` content--an _enyo.Blob_ may only be instantiated using an -`Array` or `String`. - -_enyo.FormData_ is inspired by -[html5-formdata](https://github.com/francois2metz/html5-formdata/blob/master/formdata.js). - - Emulate FormData for some browsers - MIT License - (c) 2010 Francois de Metz - - */ -(function(w) { - if (w.FormData) { - try { - var t1 = new w.FormData(); - var t2 = new w.Blob(); - // Android Chrome 18 will throw an error trying to create these - enyo.FormData = w.FormData; - enyo.Blob = w.Blob; - return; - } - catch (e) { - // ignore error and fall through to fake FormData code - } - } - function FormData() { - this.fake = true; - this._fields = []; - // This generates a 50 character boundary similar to - // those used by Firefox. They are optimized for - // boyer-moore parsing. - this.boundary = '--------------------------'; - for (var i = 0; i < 24; i++) { - this.boundary += Math.floor(Math.random() * 10).toString(16); - } - } - FormData.prototype.getContentType = function() { - return "multipart/form-data; boundary=" + this.boundary; - }; - FormData.prototype.append = function(key, value, filename) { - this._fields.push([key, value, filename]); - }; - FormData.prototype.toString = function() { - var boundary = this.boundary; - var body = ""; - enyo.forEach(this._fields, function(field) { - body += "--" + boundary + "\r\n"; - if (field[2] || field[1].name) { - // file upload - var file = field[1], filename = field[2] || file.name; - body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ filename +"\"\r\n"; - body += "Content-Type: "+ file.type +"\r\n\r\n"; - body += file.getAsBinary() + "\r\n"; - } else { - // key-value field - body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n"; - body += field[1] + "\r\n"; - } - }); - body += "--" + boundary +"--"; - return body; - }; - enyo.FormData = FormData; - - function Blob(inBufs, inOpts) { - this.name = inOpts.name; - this.type = inOpts.type || 'application/octet-stream'; - if (!enyo.isArray(inBufs)) { - throw new Error('enyo.Blob only handles Arrays of Strings'); - } - if ((inBufs.length > 0) && typeof inBufs[0] !== 'string') { - throw new Error('enyo.Blob only handles Arrays of Strings'); - } - this._bufs = inBufs; // leave byte arrays un-touched - } - Blob.prototype.getAsBinary = function() { - var empty = '', - content = empty.concat.apply(empty, this._bufs); - return content; - }; - enyo.Blob = Blob; - -})(window); diff --git a/enyo/source/ajax/json.js b/enyo/source/ajax/json.js deleted file mode 100644 index d9b7bb7..0000000 --- a/enyo/source/ajax/json.js +++ /dev/null @@ -1,21 +0,0 @@ -enyo.json = { - //* @public - /** - Returns a JSON string for a given object, using native stringify - routine. - inValue is the Object to be converted to JSON. - inReplacer is the optional value inclusion array or replacement function. - inSpace is the optional number or string to use for pretty-printing whitespace. - */ - stringify: function(inValue, inReplacer, inSpace) { - return JSON.stringify(inValue, inReplacer, inSpace); - }, - /** - Returns a JavaScript object for a given JSON string, using native stringify - routine. - inJson is the JSON string to be converted to a JavaScript object. - */ - parse: function(inJson, inReviver) { - return inJson ? JSON.parse(inJson, inReviver) : null; - } -}; diff --git a/enyo/source/ajax/package.js b/enyo/source/ajax/package.js deleted file mode 100644 index 41fca45..0000000 --- a/enyo/source/ajax/package.js +++ /dev/null @@ -1,11 +0,0 @@ -enyo.depends( - "Async.js", - "json.js", - "cookie.js", - "xhr.js", - "formdata.js", - "AjaxProperties.js", - "Ajax.js", - "Jsonp.js", - "WebService.js" -); \ No newline at end of file diff --git a/enyo/source/ajax/xhr.js b/enyo/source/ajax/xhr.js deleted file mode 100644 index cdd7fc0..0000000 --- a/enyo/source/ajax/xhr.js +++ /dev/null @@ -1,143 +0,0 @@ -//* @protected -/** - If you make changes to _enyo.xhr_, be sure to add or update the appropriate - [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests). -*/ -enyo.xhr = { - /** - inParams is an Object that may contain these properties: - - - _url_: The URL to request (required). - - _method_: The HTTP method to use for the request. Defaults to GET. - - _callback_: Called when request is completed. (Optional) - - _body_: Specific contents for the request body for POST method. (Optional) - - _headers_: Additional request headers. (Optional). Given headers override the ones that Enyo may set by default (`null` explictly removing the header from the AJAX request). - - _username_: The optional user name to use for authentication purposes. - - _password_: The optional password to use for authentication purposes. - - _xhrFields_: Optional object containing name/value pairs to mix directly into the generated xhr object. - - _mimeType_: Optional string to override the MIME-Type. - */ - request: function(inParams) { - var xhr = this.getXMLHttpRequest(inParams); - var url = enyo.path.rewrite(this.simplifyFileURL(inParams.url)); - // - var method = inParams.method || "GET"; - var async = !inParams.sync; - // - if (inParams.username) { - xhr.open(method, url, async, inParams.username, inParams.password); - } else { - xhr.open(method, url, async); - } - // - enyo.mixin(xhr, inParams.xhrFields); - // only setup handler when we have a callback - if (inParams.callback) { - this.makeReadyStateHandler(xhr, inParams.callback); - } - // - inParams.headers = inParams.headers || {}; - // work around iOS 6 bug where non-GET requests are cached - // see http://www.einternals.com/blog/web-development/ios6-0-caching-ajax-post-requests - // not sure (yet) wether this will be required for later ios releases - if (method !== "GET" && enyo.platform.ios && enyo.platform.ios >= 6) { - if (inParams.headers["cache-control"] !== null) { - inParams.headers["cache-control"] = inParams.headers['cache-control'] || "no-cache"; - } - } - // user-set headers override any platform-default - if (xhr.setRequestHeader) { - for (var key in inParams.headers) { - if (inParams.headers[key]) { - xhr.setRequestHeader(key, inParams.headers[key]); - } - } - } - // - if((typeof xhr.overrideMimeType == "function") && inParams.mimeType) { - xhr.overrideMimeType(inParams.mimeType); - } - // - xhr.send(inParams.body || null); - if (!async && inParams.callback) { - xhr.onreadystatechange(xhr); - } - return xhr; - }, - //* remove any callbacks that might be set from Enyo code for an existing XHR - //* and stop the XHR from completing. - cancel: function(inXhr) { - if (inXhr.onload) { - inXhr.onload = null; - } - if (inXhr.onreadystatechange) { - inXhr.onreadystatechange = null; - } - if (inXhr.abort) { - inXhr.abort(); - } - }, - //* @protected - makeReadyStateHandler: function(inXhr, inCallback) { - if (window.XDomainRequest && inXhr instanceof XDomainRequest) { - inXhr.onload = function() { - var text; - if (typeof inXhr.responseText === "string") { - text = inXhr.responseText; - } - inCallback.apply(null, [text, inXhr]); - }; - } - inXhr.onreadystatechange = function() { - if (inXhr.readyState == 4) { - var text; - if (typeof inXhr.responseText === "string") { - text = inXhr.responseText; - } - inCallback.apply(null, [text, inXhr]); - } - }; - }, - inOrigin: function(inUrl) { - var a = document.createElement("a"), result = false; - a.href = inUrl; - // protocol is ":" for relative URLs - if (a.protocol === ":" || - (a.protocol === window.location.protocol && - a.hostname === window.location.hostname && - a.port === (window.location.port || - (window.location.protocol === "https:" ? "443" : "80")))) { - result = true; - } - return result; - }, - simplifyFileURL: function(inUrl) { - var a = document.createElement("a"), result = false; - a.href = inUrl; - // protocol is ":" for relative URLs - if (a.protocol === "file:" || - a.protocol === ":" && window.location.protocol === "file:") { - // leave off search and hash parts of the URL - return a.protocol + '//' + a.host + a.pathname; - } else if (a.protocol === ":" && window.location.protocol === "x-wmapp0:") { - // explicitly return absolute URL for Windows Phone 8, as an absolute path is required for local files - return window.location.protocol + "//" + window.location.pathname.split('/')[0] + "/" + a.host + a.pathname; - } else { - return inUrl; - } - }, - getXMLHttpRequest: function(inParams) { - try { - // only use XDomainRequest when it exists, no extra headers were set, and the - // target URL maps to a domain other than the document origin. - if (enyo.platform.ie < 10 && window.XDomainRequest && !inParams.headers && - !this.inOrigin(inParams.url) && !/^file:\/\//.test(window.location.href)) { - return new XDomainRequest(); - } - } catch(e) {} - try { - return new XMLHttpRequest(); - } catch(e) {} - return null; - } -}; diff --git a/enyo/source/boot/boot.js b/enyo/source/boot/boot.js deleted file mode 100644 index 18a67f7..0000000 --- a/enyo/source/boot/boot.js +++ /dev/null @@ -1,133 +0,0 @@ -// Used when a certain platform restricts functionality due to security -enyo.execUnsafeLocalFunction = function(e) { - // Querying {MSApp} object - Windows 8 - if (typeof MSApp === "undefined") { - e(); - } - else { - MSApp.execUnsafeLocalFunction(e); - } -}; - -// machine for a loader instance -enyo.machine = { - sheet: function(inPath) { - var type = "text/css"; - var rel = "stylesheet"; - var isLess = (inPath.slice(-5) == ".less"); - if (isLess) { - if (window.less) { - // If client-side less is loaded, insert the less stylesheet - type = "text/less"; - rel = "stylesheet/less"; - } else { - // Otherwise, we expect a css file of the same name to exist - inPath = inPath.slice(0, inPath.length-4) + "css"; - } - } - var link; - if (enyo.runtimeLoading || isLess) { - link = document.createElement('link'); - link.href = inPath; - link.media = "screen"; - link.rel = rel; - link.type = type; - document.getElementsByTagName('head')[0].appendChild(link); - } else { - link = function() { - document.write(''); - }; - enyo.execUnsafeLocalFunction(link); - } - if (isLess && window.less) { - less.sheets.push(link); - if (!enyo.loader.finishCallbacks.lessRefresh) { - enyo.loader.finishCallbacks.lessRefresh = function() { - less.refresh(true); - }; - } - } - }, - script: function(inSrc, onLoad, onError) { - if (!enyo.runtimeLoading) { - document.write(''); - } else { - var script = document.createElement('script'); - script.src = inSrc; - script.onload = onLoad; - script.onerror = onError; - document.getElementsByTagName('head')[0].appendChild(script); - } - }, - inject: function(inCode) { - document.write('' + inCode + ""); - } -}; - -// create a dependency processor using our script machine -enyo.loader = new enyo.loaderFactory(enyo.machine); - -// dependency API uses enyo loader -enyo.depends = function() { - var ldr = enyo.loader; - if (!ldr.packageFolder) { - var tag = enyo.locateScript("package.js"); - if (tag && tag.path) { - ldr.aliasPackage(tag.path); - ldr.packageFolder = tag.path + "/"; - //console.log("detected PACKAGEFOLDER [" + ldr.packageFolder + "]"); - } - } - ldr.load.apply(ldr, arguments); -}; - -// Runtime loader -// Usage: enyo.load(depends, [onLoadCallback]) -// where - depends is string or array of string paths to package.js, script, or css to load -// - doneCallback is fired after file or package loading has completed -// Only one file/package is loaded at a time; additional calls are queued and loading deferred -(function() { - var enyo = window.enyo; - var runtimeLoadQueue = []; - enyo.load = function(depends, onLoadCallback) { - runtimeLoadQueue.push(arguments); - if (!enyo.runtimeLoading) { - enyo.runtimeLoading = true; - runtimeLoad(); - } - }; - function runtimeLoad(onLoad) { - if (onLoad) { - onLoad(); // Run user callback function - } - if (runtimeLoadQueue.length) { - var args = runtimeLoadQueue.shift(); - var depends = args[0]; - var dependsArg = enyo.isArray(depends) ? depends : [depends]; - var onLoadCallback = args[1]; - enyo.loader.finishCallbacks.runtimeLoader = function() { - // Once loader is done loading a package, we chain a call to runtimeLoad(), - // which will call the onLoadCallback from the original load call, passing - // a reference to the depends argument from the original call for tracking, - // followed by kicking off any additionally queued load() calls - runtimeLoad(function() { - if (onLoadCallback) { - onLoadCallback(depends); - } - }); - }; - enyo.loader.packageFolder = "./"; - // Kick off next queued call to loader - enyo.depends.apply(this, dependsArg); - } else { - enyo.runtimeLoading = false; - enyo.loader.packageFolder = ""; - } - } -})(); - -// predefined path aliases -enyo.path.addPaths({ - enyo: enyo.args.root, - lib: "$enyo/../lib" -}); \ No newline at end of file diff --git a/enyo/source/boot/enyo.js b/enyo/source/boot/enyo.js deleted file mode 100644 index a1126d5..0000000 --- a/enyo/source/boot/enyo.js +++ /dev/null @@ -1,31 +0,0 @@ -(function() { - // enyo can use information from the script tag that loads this bootstrap file - var thisScript = "enyo.js"; - - enyo = window.enyo || {}; - - enyo.locateScript = function(inName) { - var scripts = document.getElementsByTagName("script"); - for (var i=scripts.length-1, s, src, l=inName.length; (i>=0) && (s=scripts[i]); i--) { - if (!s.located) { - src = s.getAttribute("src") || ""; - if (src.slice(-l) == inName) { - s.located = true; - return {path: src.slice(0, Math.max(0, src.lastIndexOf("/"))), node: s}; - } - } - } - }; - - enyo.args = enyo.args || {}; - - var tag = enyo.locateScript(thisScript); - if (tag) { - // infer the framework path from the document, unless the user has specified one explicitly - enyo.args.root = (enyo.args.root || tag.path).replace("/source", ""); - // all attributes of the bootstrap script tag become enyo.args - for (var i=0, al = tag.node.attributes.length, it; (i < al) && (it = tag.node.attributes.item(i)); i++) { - enyo.args[it.nodeName] = it.value; - } - } -})(); \ No newline at end of file diff --git a/enyo/source/boot/package.js b/enyo/source/boot/package.js deleted file mode 100644 index adc2873..0000000 --- a/enyo/source/boot/package.js +++ /dev/null @@ -1,5 +0,0 @@ -enyo.depends( - "enyo.js", - "../../loader.js", - "boot.js" -); \ No newline at end of file diff --git a/enyo/source/dom/Control.js b/enyo/source/dom/Control.js deleted file mode 100644 index 1ea3bea..0000000 --- a/enyo/source/dom/Control.js +++ /dev/null @@ -1,879 +0,0 @@ -/** - _enyo.Control_ is a component that controls a DOM node (i.e., an element in - the user interface). Controls are generally visible and the user often - interacts with them directly. While things like buttons and input boxes are - obviously controls, in Enyo, a control may become as complex as an entire - application. - - If you make changes to _enyo.Control_, be sure to add or update the appropriate - [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). - - For more information, see the documentation on - Controls - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Control", - kind: enyo.UiComponent, - published: { - /** - HTML tag name to use for the control. If null, no tag is generated; - only the contents are used. - */ - tag: "div", - //* Hash of DOM attributes to apply to the generated HTML tag - attributes: null, - //* Space-delimited set of CSS classes to apply to the generated HTML tag - classes: "", - //* Style attribute to apply to the generated HTML tag - style: "", - /** - Content that will be generated inside the HTML tag; defaults to - plain text unless _allowHtml_ is true - */ - content: "", - //* Boolean indicating whether the tag will be visible in the document - showing: true, - //* If false, HTML codes in _content_ are escaped before rendering - allowHtml: false, - // - // convenience properties for common attributes - // - //* Shortcut for setting _src_ attribute in _attributes_ hash. Overrides that value. - src: "", - // - // esoteric - // - /** - Set to false if the control should not generate any HTML. Used to - inhibit generation of popups until they're shown at runtime. - */ - canGenerate: true, - // - // ad hoc properties: - // - /** - Flag used by control layouts to determine which control will expand - to fill the available space. This only has meaning when the control - is being used as a child of a control with a version of FittableLayout - as its layoutKind. - */ - fit: false, - //* Used by Ares design editor for design objects - isContainer: false - }, - handlers: { - //* Controls will call a user-provided _tap_ method when tapped upon. - ontap: "tap" - }, - //* The default kind for controls created inside this control that don't - //* specify their own kind - defaultKind: "Control", - //* A set of CSS classes that are applied to controls created inside this control - controlClasses: "", - //* @protected - node: null, - generated: false, - create: function() { - // initialize style databases - this.initStyles(); - // superkind initialization - this.inherited(arguments); - // 'showing' is tertiary method for modifying display style - // setting 'display: none;' style at initialization time will - // not work if 'showing' is true. - this.showingChanged(); - // Notes: - // - 'classes' does not reflect the complete set of classes on an object; the complete set is in - // this.attributes.class. The '*Class' apis affect this.attributes.class. - // - use addClass instead of setClasses here, by convention 'classes' is reserved for instance objects - // - inheritors should 'addClass' to add classes - // - setClasses removes the old classes and adds the new one, setClassAttribute replaces all classes - this.addClass(this.kindClasses); - this.addClass(this.classes); - this.initProps(["id", "content", "src"]); - }, - destroy: function() { - this.removeNodeFromDom(); - enyo.Control.unregisterDomEvents(this.id); - this.inherited(arguments); - }, - importProps: function(inProps) { - this.inherited(arguments); - // each instance has its own attributes array, the union of the prototype attributes and user-specified attributes - this.attributes = enyo.mixin(enyo.clone(this.kindAttributes), this.attributes); - }, - initProps: function(inPropNames) { - // for each named property, trigger the *Changed handler if the property value is truthy - for (var i=0, n, cf; (n=inPropNames[i]); i++) { - if (this[n]) { - // FIXME: awkward - cf = n + "Changed"; - if (this[cf]) { - this[cf](); - } - } - } - }, - classesChanged: function(inOld) { - this.removeClass(inOld); - this.addClass(this.classes); - }, - // modify components we create ourselves - /* - adjustComponentProps: function(inProps) { - if (this.controlClasses) { - inProps.classes = (inProps.classes ? inProps.classes + " " : "") + this.controlClasses; - } - this.inherited(arguments); - }, - */ - addChild: function(inControl) { - inControl.addClass(this.controlClasses); - this.inherited(arguments); - }, - removeChild: function(inControl) { - this.inherited(arguments); - inControl.removeClass(this.controlClasses); - }, - // event filter - strictlyInternalEvents: {onenter: 1, onleave: 1}, - dispatchEvent: function(inEventName, inEvent, inSender) { - // prevent dispatch and bubble of events that are strictly internal (e.g. enter/leave) - if (this.strictlyInternalEvents[inEventName] && this.isInternalEvent(inEvent)) { - return true; - } - return this.inherited(arguments); - }, - isInternalEvent: function(inEvent) { - var rdt = enyo.dispatcher.findDispatchTarget(inEvent.relatedTarget); - return rdt && rdt.isDescendantOf(this); - }, - // - //* @public - /** - Returns the DOM node representing the control. - If the control is not currently rendered, returns null. - - If hasNode() returns a value, the _node_ property will be valid and - can be checked directly. - - Once hasNode() is called, the returned value is made available in - the _node_ property of this control. - - A control will only return a node if it has been rendered. - - if (this.hasNode()) { - enyo.log(this.node.nodeType); - } - */ - hasNode: function() { - // 'generated' is used to gate access to expensive findNodeById call - return this.generated && (this.node || this.findNodeById()); - }, - /** - Appends the string value of _inAddendum_ to the _content_ of this - control. - */ - addContent: function(inAddendum) { - this.setContent(this.content + inAddendum); - }, - /** - Gets the value of an attribute on this object. - - If this control has a node, the attribute value is retrieved from the - node; otherwise, it's read from the _attributes_ property of the control - itself. - - Caveat: If the control is rendered, the _attributes_ property is used to - construct the rendering, and values that have changed on the node itself - are lost. - - // Get the value attribute for this DomNode - var value = this.getAttribute("tabIndex"); - */ - getAttribute: function(inName) { - return this.hasNode() ? this.node.getAttribute(inName) : this.attributes[inName]; - }, - /** - Sets the value of an attribute on this object. Pass null _inValue_ to - remove an attribute. - - // set the tabIndex attribute for this DomNode - this.setAttribute("tabIndex", 3); - ... - // remove the index attribute - this.setAttribute("index", null); - */ - setAttribute: function(inName, inValue) { - this.attributes[inName] = inValue; - if (this.hasNode()) { - this.attributeToNode(inName, inValue); - } - this.invalidateTags(); - }, - /** - Gets the value of a property named _inName_ directly from the DOM node. - A caller-specified default value, _inDefault_, is returned when the DOM - node has not yet been created. - */ - getNodeProperty: function(inName, inDefault) { - if (this.hasNode()) { - return this.node[inName]; - } else { - return inDefault; - } - }, - /** - Sets the value of the _inName_ property on the control's DOM node to - _inValue_, if and only if the DOM node has been rendered. This method - does not alter any values cached in local properties of the - _enyo.Control_ instance. - */ - setNodeProperty: function(inName, inValue) { - if (this.hasNode()) { - this.node[inName] = inValue; - } - }, - /** - Convenience function for setting the _class_ attribute. - The _class_ attribute represents the CSS classes assigned to this object; - it is a string that can contain multiple CSS classes separated by spaces. - - this.$.control.setClassAttribute("box blue-border highlighted"); - */ - setClassAttribute: function(inClass) { - this.setAttribute("class", inClass); - }, - /** - Convenience function for getting the _class_ attribute. - The _class_ attribute represents the CSS classes assigned to this object; - it is a string that can contain multiple CSS classes separated by spaces. - - var cssClasses = this.$.control.getClassAttribute(); - */ - getClassAttribute: function() { - return this.attributes["class"] || ""; - }, - /** - Returns true if the _class_ attribute contains a substring matching - _inClass_. - - The _class_ attribute is a string that can contain multiple CSS classes. - This method tests whether a particular class is part of the set of - classes on this control. - - // returns true if _class_ is "bar foo baz", but false for "barfoobaz" - var hasFooClass = this.$.control.hasClass("foo"); - */ - hasClass: function(inClass) { - return inClass && ((" " + this.getClassAttribute() + " ").indexOf(" " + inClass + " ") >= 0); - }, - /** - Adds CSS class name _inClass_ to the _class_ attribute of this object. - - // add the highlight class to this object - this.addClass("highlight"); - */ - addClass: function(inClass) { - if (inClass && !this.hasClass(inClass)) { - var c = this.getClassAttribute(); - this.setClassAttribute(c + (c ? " " : "") + inClass); - } - }, - /** - Removes substring _inClass_ from the _class_ attribute of this object. - - _inClass_ must have no leading or trailing spaces. - - Using a compound class name is supported, but the name is treated - atomically. For example, given _"a b c"_, _removeClass("a b")_ will - produce _"c"_, but _removeClass("a c")_ will produce _"a b c"_. - - // remove the highlight class from this object - this.removeClass("highlight"); - */ - removeClass: function(inClass) { - if (inClass && this.hasClass(inClass)) { - var c = this.getClassAttribute(); - c = (" " + c + " ").replace(" " + inClass + " ", " ").slice(1, -1); - this.setClassAttribute(c); - } - }, - /** - Adds or removes substring _inClass_ from the _class_ attribute of this - object based on the value of _inTrueToAdd_. - - If _inTrueToAdd_ is truthy, then _inClass_ is added; otherwise, - _inClass_ is removed. - - // add or remove the highlight class, depending on the "highlighted" property - this.addRemoveClass("highlight", this.highlighted); - */ - addRemoveClass: function(inClass, inTrueToAdd) { - this[inTrueToAdd ? "addClass" : "removeClass"](inClass); - }, - // - // styles - // - //* @protected - initStyles: function() { - this.domStyles = this.domStyles || {}; - enyo.Control.cssTextToDomStyles(this.kindStyle, this.domStyles); - this.domCssText = enyo.Control.domStylesToCssText(this.domStyles); - }, - styleChanged: function() { - // FIXME: stomping on domStyles is problematic, there may be styles on this object - // applied by layouts or other objects. - // We may need a 'runtimeStyles' concept separate from a 'userStyles' concept, although - // it's not clear what API calls like 'applyStyle' would affect, and which concept would take - // precedence when there is a conflict. - // Perhaps we can separate 'style' completely from 'domStyles'. API methods like applyStyle - // would affect domStyles, and the two style databases would be combined at render-time. - // Alternatively, we can disallow changing "style" string at runtime and allow it to be set - // at init-time only (as it was in pre-ares enyo). - //this.domStyles = {}; - //this.addStyles(this.kindStyle); - //this.addStyles(this.style); - this.invalidateTags(); - this.renderStyles(); - }, - //* @public - /** - Applies a single style value to this object. - - this.$.box.applyStyle("z-index", 4); - - You may remove a style by setting its value to null. - - this.$.box.applyStyle("z-index", null); - */ - applyStyle: function(inStyle, inValue) { - this.domStyles[inStyle] = inValue; - this.domStylesChanged(); - }, - /** - Adds CSS styles to the set of styles assigned to this object. - - _inCssText_ is a string containing CSS styles in text format. - - this.$.box.addStyles("background-color: red; padding: 4px;"); - */ - addStyles: function(inCssText) { - enyo.Control.cssTextToDomStyles(inCssText, this.domStyles); - this.domStylesChanged(); - }, - /** - Returns the computed value of a CSS style named from _inStyle_ - for the DOM node of the control. If the node hasn't been generated, - returns _inDefault_ as a default value. This uses JavaScript-style - property names, not CSS-style names, so use "fontFamily" instead of - "font-family". - */ - getComputedStyleValue: function(inStyle, inDefault) { - if (this.hasNode()) { - return enyo.dom.getComputedStyleValue(this.node, inStyle); - } - return inDefault; - }, - //* @protected - domStylesChanged: function() { - this.domCssText = enyo.Control.domStylesToCssText(this.domStyles); - this.invalidateTags(); - this.renderStyles(); - }, - stylesToNode: function() { - this.node.style.cssText = this.style + (this.style[this.style.length-1] == ';' ? ' ' : '; ') + this.domCssText; - }, - setupBodyFitting: function() { - enyo.dom.applyBodyFit(); - this.addClass("enyo-fit enyo-clip"); - }, - /* - If the platform is Android or Android-Chrome, don't include - the css rule -webkit-overflow-scrolling: touch, as it is - not supported in Android and leads to overflow issues - (ENYO-900 and ENYO-901) - Similarly, BB10 has issues repainting out-of-viewport content - when -webkit-overflow-scrolling is used (ENYO-1396) - */ - setupOverflowScrolling: function() { - if(enyo.platform.android || enyo.platform.androidChrome || enyo.platform.blackberry) - return; - document.getElementsByTagName("body")[0].className += " webkitOverflowScrolling"; - }, - // - // - //* @public - /** - Renders this object into DOM, generating a DOM node if needed. - */ - render: function() { - if (this.parent) { - // allow the parent to perform setup tasks - // note: ('parent.generated' may change here) - this.parent.beforeChildRender(this); - // don't render if the parent has not generated - if (!this.parent.generated) { - return this; - } - } - if (!this.hasNode()) { - this.renderNode(); - } - if (this.hasNode()) { - this.renderDom(); - if (this.generated) { - this.rendered(); - } - } - // return 'this' to support method chaining - return this; - }, - /** - Renders this object into the DOM node referenced by _inParentNode_. - If rendering into the document body element, appropriate styles will - be used to have it expand to fill the whole window. - */ - renderInto: function(inParentNode) { - // clean up render flags and memoizations - this.teardownRender(); - // inParentNode can be a string id or a node reference - var pn = enyo.dom.byId(inParentNode); - if (pn == document.body) { - this.setupBodyFitting(); - } else if (this.fit) { - this.addClass("enyo-fit enyo-clip"); - } - // for IE10 support, we want full support over touch actions in Enyo-rendered areas - this.addClass("enyo-no-touch-action"); - // add css to enable hw-accelerated scrolling on non-Android platforms (ENYO-900, ENYO-901) - this.setupOverflowScrolling(); - // generate our HTML - enyo.dom.setInnerHtml(pn, this.generateHtml()); - // post-rendering tasks - if (this.generated) { - this.rendered(); - } - // support method chaining - return this; - }, - /** - Uses _document.write_ to output the control into the document. - If the control has _fit: true_ defined, appropriate styles will be set - to have it expand to fill its container. - - Note that this has all the limitations that _document.write_ has. - It only works while the page is loading, so you can't call this from an - event handler. Also, it will not work in certain environments, such as - Chrome Packaged Apps or Windows 8. - */ - write: function() { - if (this.fit) { - this.setupBodyFitting(); - } - // for IE10 support, we want full support over touch actions in Enyo-rendered areas - this.addClass("enyo-no-touch-action"); - // add css to enable hw-accelerated scrolling on non-Android platforms (ENYO-900, ENYO-901) - this.setupOverflowScrolling(); - document.write(this.generateHtml()); - // post-rendering tasks - if (this.generated) { - this.rendered(); - } - // support method chaining - return this; - }, - /** - Override this method to perform tasks that require access to the DOM node. - - rendered: function() { - this.inherited(arguments); - // do some task - } - */ - rendered: function() { - // CAVEAT: Currently we use one entry point ('reflow') for - // post-render layout work *and* post-resize layout work. - this.reflow(); - for (var i=0, c; (c=this.children[i]); i++) { - if (c.generated) { - c.rendered(); - } - } - }, - /** - Shows this node (alias for _setShowing(true)_). - */ - show: function() { - this.setShowing(true); - }, - /** - Hides this node (alias for _setShowing(false)_). - */ - hide: function() { - this.setShowing(false); - }, - /** - Returns an object describing the geometry of this object, like so: - - {left: _offsetLeft_, top: _offsetTop_, width: _offsetWidth_, height: _offsetHeight_} - - Values returned are only valid if _hasNode()_ is truthy. - If there's no DOM node for the object, this returns a bounds structure with - _undefined_ as the value of all fields. - - var bounds = this.getBounds(); - enyo.log(bounds.width); - */ - getBounds: function() { - var n = this.node || this.hasNode(); - var b = enyo.dom.getBounds(n); - return b || {left: undefined, top: undefined, width: undefined, height: undefined}; - }, - /** - Sets any or all of the geometry style properties _width_, _height_, - _left_, _top_, _right_ and _bottom_. - - Values may be specified as strings (with units included), or as numbers - when a unit is provided in _inUnit_. - - this.setBounds({width: 100, height: 100}, "px"); // adds style properties like "width: 100px; height: 100px;" - // - this.setBounds({width: "10em", right: "30pt"}); // adds style properties like "width: 10em; right: 30pt;" - */ - setBounds: function(inBounds, inUnit) { - var s = this.domStyles, unit = inUnit || "px"; - var extents = ["width", "height", "left", "top", "right", "bottom"]; - for (var i=0, b, e; (e=extents[i]); i++) { - b = inBounds[e]; - if (b || b === 0) { - s[e] = b + (!enyo.isString(b) ? unit : ''); - } - } - this.domStylesChanged(); - }, - //* @protected - // expensive, other methods do work to avoid calling here - findNodeById: function() { - return this.id && (this.node = enyo.dom.byId(this.id)); - }, - idChanged: function(inOld) { - if (inOld) { - enyo.Control.unregisterDomEvents(inOld); - } - this.setAttribute("id", this.id); - if (this.id) { - enyo.Control.registerDomEvents(this.id, this); - } - }, - contentChanged: function() { - if (this.hasNode()) { - this.renderContent(); - } - }, - getSrc: function() { - return this.getAttribute("src"); - }, - srcChanged: function() { - this.setAttribute("src", enyo.path.rewrite(this.src)); - }, - attributesChanged: function() { - this.invalidateTags(); - this.renderAttributes(); - }, - // - // HTML rendering - // - generateHtml: function() { - if (this.canGenerate === false) { - return ''; - } - // do this first in case content generation affects outer html (styles or attributes) - var c = this.generateInnerHtml(); - // generate tag, styles, attributes - var h = this.generateOuterHtml(c); - // NOTE: 'generated' is used to gate access to findNodeById in - // hasNode, because findNodeById is expensive. - // NOTE: we typically use 'generated' to mean 'created in DOM' - // but that has not actually happened at this point. - // We set 'generated = true' here anyway to avoid having to walk the - // control tree a second time (to set it later). - // The contract is that insertion in DOM will happen synchronously - // to generateHtml() and before anybody should be calling hasNode(). - this.generated = true; - return h; - }, - generateInnerHtml: function() { - // Flow can alter the way that html content is rendered inside - // the container regardless of whether there are children. - this.flow(); - if (this.children.length) { - return this.generateChildHtml(); - } else { - return this.allowHtml ? this.content : enyo.Control.escapeHtml(this.content); - } - }, - generateChildHtml: function() { - var results = ''; - for (var i=0, c; (c=this.children[i]); i++) { - var h = c.generateHtml(); - results += h; - } - return results; - }, - generateOuterHtml: function(inContent) { - if (!this.tag) { - return inContent; - } - if (!this.tagsValid) { - this.prepareTags(); - } - return this._openTag + inContent + this._closeTag; - }, - invalidateTags: function() { - this.tagsValid = false; - }, - prepareTags: function() { - var htmlStyle = this.domCssText + this.style; - this._openTag = '<' + - this.tag + - (htmlStyle ? ' style="' + htmlStyle + '"' : "") + - enyo.Control.attributesToHtml(this.attributes); - if (enyo.Control.selfClosing[this.tag]) { - this._openTag += '/>'; - this._closeTag = ''; - } else { - this._openTag += '>'; - this._closeTag = ''; - } - this.tagsValid = true; - }, - // DOM, aka direct-to-node, rendering - attributeToNode: function(inName, inValue) { - if (inValue === null || inValue === false || inValue === "") { - this.node.removeAttribute(inName); - } else { - this.node.setAttribute(inName, inValue); - } - }, - attributesToNode: function() { - for (var n in this.attributes) { - this.attributeToNode(n, this.attributes[n]); - } - }, - getParentNode: function() { - return this.parentNode || (this.parent && (this.parent.hasNode() || this.parent.getParentNode())); - }, - addNodeToParent: function() { - if (this.node) { - var pn = this.getParentNode(); - if (pn) { - if (this.addBefore !== undefined) { - this.insertNodeInParent(pn, this.addBefore && this.addBefore.hasNode()); - } else { - this.appendNodeToParent(pn); - } - } - } - }, - appendNodeToParent: function(inParentNode) { - inParentNode.appendChild(this.node); - }, - insertNodeInParent: function(inParentNode, inBeforeNode) { - inParentNode.insertBefore(this.node, inBeforeNode || inParentNode.firstChild); - }, - removeNodeFromDom: function() { - if (this.hasNode() && this.node.parentNode) { - this.node.parentNode.removeChild(this.node); - } - }, - teardownRender: function() { - if (this.generated) { - this.teardownChildren(); - } - this.node = null; - this.generated = false; - }, - teardownChildren: function() { - for (var i=0, c; (c=this.children[i]); i++) { - c.teardownRender(); - } - }, - renderNode: function() { - this.teardownRender(); - this.node = document.createElement(this.tag); - this.addNodeToParent(); - this.generated = true; - }, - renderDom: function() { - this.renderAttributes(); - this.renderStyles(); - this.renderContent(); - }, - renderContent: function() { - if (this.generated) { - this.teardownChildren(); - } - enyo.dom.setInnerHtml(this.node, this.generateInnerHtml()); - }, - renderStyles: function() { - if (this.hasNode()) { - this.stylesToNode(); - } - }, - renderAttributes: function() { - if (this.hasNode()) { - this.attributesToNode(); - } - }, - beforeChildRender: function() { - // if we are generated, we should flow before rendering a child - // if not, the render context isn't ready anyway - if (this.generated) { - this.flow(); - } - }, - syncDisplayToShowing: function() { - var ds = this.domStyles; - if (this.showing) { - // note: only show a node if it's actually hidden - // this way we prevent overriding the value of domStyles.display - if (ds.display == "none") { - this.applyStyle("display", this._displayStyle || ""); - } - } else { - // cache the previous showing value of display - // note: we could use a class to hide a node, but then - // hide would not override a setting of display: none in style, - // which seems bad. - this._displayStyle = (ds.display == "none" ? "" : ds.display); - this.applyStyle("display", "none"); - } - }, - showingChanged: function() { - this.syncDisplayToShowing(); - }, - getShowing: function() { - // 'showing' specifically means domStyles.display !== 'none'. - // 'showing' does not imply the node is actually visible or even rendered in DOM, - // it simply reflects this state of this specific property as a convenience. - return this.showing = (this.domStyles.display != "none"); - }, - // - // - fitChanged: function(inOld) { - this.parent.reflow(); - }, - // - // - statics: { - /** - Returns passed-in string with ampersand, less-than, and greater-than - characters replaced by HTML entities, e.g., - '<code>"This & That"</code>' becomes - '&lt;code&gt;"This &amp; That"&lt;/code&gt;' - */ - escapeHtml: function(inText) { - return inText != null ? String(inText).replace(/&/g,'&').replace(//g,'>') : ''; - }, - //* @protected - registerDomEvents: function(inId, inControl) { - enyo.$[inId] = inControl; - }, - unregisterDomEvents: function(inId) { - enyo.$[inId] = null; - }, - selfClosing: {img: 1, hr: 1, br: 1, area: 1, base: 1, basefont: 1, input: 1, link: 1, meta: 1, - command: 1, embed: 1, keygen: 1, wbr: 1, param: 1, source: 1, track: 1, col: 1}, - cssTextToDomStyles: function(inText, inStyleHash) { - if (inText) { - // remove spaces between rules, then split rules on delimiter (;) - var rules = inText.replace(/; /g, ";").split(";"); - // parse string styles into name/value pairs - for (var i=0, s, n, v, rule; (rule=rules[i]); i++) { - // "background-image: url(http://foo.com/foo.png)" => ["background-image", "url(http", "//foo.com/foo.png)"] - s = rule.split(":"); - // n = "background-image", s = ["url(http", "//foo.com/foo.png)"] - n = s.shift(); - // v = ["url(http", "//foo.com/foo.png)"].join(':') = "url(http://foo.com/foo.png)" - v = s.join(':'); - // store name/value pair - inStyleHash[n] = v; - } - } - }, - domStylesToCssText: function(inStyleHash) { - var n, v, text = ''; - for (n in inStyleHash) { - v = inStyleHash[n]; - if ((v !== null) && (v !== undefined) && (v !== "")) { - text += n + ':' + v + ';'; - } - } - return text; - }, - stylesToHtml: function(inStyleHash) { - var cssText = enyo.Control.domStylesToCssText(inStyleHash); - return (cssText ? ' style="' + cssText + '"' : ""); - }, - /** - Returns passed-in string with ampersand and double quote characters - replaced by HTML entities, e.g., 'hello from "Me & She"' becomes - 'hello from &quot;Me &amp; She&quot;' - */ - escapeAttribute: function(inText) { - return !enyo.isString(inText) ? inText : String(inText).replace(/&/g,'&').replace(/\"/g,'"'); - }, - attributesToHtml: function(inAttributeHash) { - var n, v, h = ''; - for (n in inAttributeHash) { - v = inAttributeHash[n]; - if (v !== null && v !== false && v !== "") { - h += ' ' + n + '="' + enyo.Control.escapeAttribute(v) + '"'; - } - } - return h; - } - } -}); - -enyo.defaultCtor = enyo.Control; - -enyo.Control.subclass = function(ctor, props) { - // Control classes may declare properties that are intended - // to stack with superclass properties. - // - // We resort to prototype magic to assemble these properties - // at kind declaration time, in the interest of efficiency - // and ease of use. - // - // However, the properties are no longer 'live' in prototypes - // because of this magic--i.e., changes to the prototype of - // a Control subclass will not necessarily be reflected in - // instances of that control (e.g., chained prototypes). - // - // These properties are also renamed to kind* to allow - // combining with instance properties. - // - var proto = ctor.prototype; - // - // 'kindClasses' comes either from our inheritance chain (e.g., proto's prototype chain) - // or has been forced by a kind declaration. - // - if (proto.classes) { - var kc = proto.kindClasses; - proto.kindClasses = (kc ? kc + " " : "") + proto.classes; - proto.classes = ""; - } - if (proto.style) { - var ks = proto.kindStyle; - proto.kindStyle = (ks ? ks + ";" : "") + proto.style; - proto.style = ""; - } - if (props.attributes) { - var ka = proto.kindAttributes; - proto.kindAttributes = enyo.mixin(enyo.clone(ka), proto.attributes); - proto.attributes = null; - } -}; diff --git a/enyo/source/dom/animation.js b/enyo/source/dom/animation.js deleted file mode 100644 index 13c7af0..0000000 --- a/enyo/source/dom/animation.js +++ /dev/null @@ -1,99 +0,0 @@ -(function() { - var ms = Math.round(1000/60); - var prefix = ["webkit", "moz", "ms", "o", ""]; - var r = "requestAnimationFrame"; - var c = "cancel" + enyo.cap(r); - // fallback on setTimeout and clearTimeout - var _requestFrame = function(inCallback) { - return window.setTimeout(inCallback, ms); - }; - var _cancelFrame = function(inId) { - return window.clearTimeout(inId); - }; - for (var i = 0, pl = prefix.length, p, wc, wr; (p = prefix[i]) || i < pl; i++) { - // if we're on ios 6 just use setTimeout, requestAnimationFrame has some kinks currently - if (enyo.platform.ios >= 6) { - break; - } - - // if prefixed, becomes Request and Cancel - wc = p ? (p + enyo.cap(c)) : c; - wr = p ? (p + enyo.cap(r)) : r; - // Test for cancelRequestAnimationFrame, because some browsers (Firefix 4-10) have a request without a cancel - if (window[wc]) { - _cancelFrame = window[wc]; - _requestFrame = window[wr]; - if (p == "webkit") { - /* - Note: In Chrome, the first return value of webkitRequestAnimationFrame is 0. - We make 1 bogus call so the first used return value of webkitRequestAnimationFrame is > 0, as the spec requires. - This makes it so that the requestId is always truthy. - (we choose to do this rather than wrapping the native function to avoid the overhead) - */ - _cancelFrame(_requestFrame(enyo.nop)); - } - break; - } - } - /** - Requests an animation callback. - - On compatible browsers, if _inNode_ is defined, the callback will fire only if _inNode_ is visible. - - Returns a request id to be used with [enyo.cancelRequestAnimationFrame](#enyo.cancelRequestAnimationFrame). - */ - enyo.requestAnimationFrame = function(inCallback, inNode) { - return _requestFrame(inCallback, inNode); - }; - /** - Cancels a requested animation callback with the specified id. - */ - enyo.cancelRequestAnimationFrame = function(inId) { - return _cancelFrame(inId); - }; -})(); - -/** - An assortment of interpolation functions for animations. - - Similar in function to CSS3 transitions. - - Intended for use with [enyo.easedLerp](#enyo.easedLerp) -*/ -enyo.easing = { - cubicIn: function(n) { - return Math.pow(n, 3); - }, - cubicOut: function(n) { - return Math.pow(n - 1, 3) + 1; - }, - expoOut: function(n) { - return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1); - }, - quadInOut: function(n){ - n = n * 2; - if (n < 1) { - return Math.pow(n, 2) / 2; - } - return -1 * ((--n) * (n - 2) - 1) / 2; - }, - linear: function(n) { - return n; - } -}; - -/** - Gives an interpolation of an animated transition's distance from 0 to 1. - - Given a start time (_inT0_) and an animation duration (_inDuration_), applies - the _inEasing_ function to the percentage of time elapsed / duration, capped - at 100%. -*/ -enyo.easedLerp = function(inT0, inDuration, inEasing, reverse) { - var lerp = (enyo.now() - inT0) / inDuration; - if (reverse) { - return lerp >= 1 ? 0 : (1 - inEasing(1 - lerp)); - } else { - return lerp >= 1 ? 1 : inEasing(lerp); - } -}; diff --git a/enyo/source/dom/dispatcher.js b/enyo/source/dom/dispatcher.js deleted file mode 100644 index 9b8da00..0000000 --- a/enyo/source/dom/dispatcher.js +++ /dev/null @@ -1,177 +0,0 @@ -//* @protected -enyo.$ = {}; - -enyo.dispatcher = { - // these events come from document - events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel", - "click", "dblclick", "change", "keydown", "keyup", "keypress", "input"], - // these events come from window - windowEvents: ["resize", "load", "unload", "message"], - // these events come from css - cssEvents: ["webkitTransitionEnd", "transitionend"], - // feature plugins (aka filters) - features: [], - connect: function() { - var d = enyo.dispatcher, i, n; - for (i=0; (n=d.events[i]); i++) { - d.listen(document, n); - } - for (i=0; (n=d.cssEvents[i]); i++) { - d.listen(document, n); - } - for (i=0; (n=d.windowEvents[i]); i++) { - // Chrome Packaged Apps don't like "unload" - if(n === "unload" && - (typeof window.chrome === "object") && - window.chrome.app) { - continue; - } - - d.listen(window, n); - } - for (i=0; (n=d.cssEvents[i]); i++) { - d.listen(document, n); - } - }, - listen: function(inListener, inEventName, inHandler) { - var d = enyo.dispatch; - if (inListener.addEventListener) { - this.listen = function(inListener, inEventName, inHandler) { - inListener.addEventListener(inEventName, inHandler || d, false); - }; - } else { - //enyo.log("IE8 COMPAT: using 'attachEvent'"); - this.listen = function(inListener, inEvent, inHandler) { - inListener.attachEvent("on" + inEvent, function(e) { - e.target = e.srcElement; - if (!e.preventDefault) { - e.preventDefault = enyo.iePreventDefault; - } - return (inHandler || d)(e); - }); - }; - } - this.listen(inListener, inEventName, inHandler); - }, - //* Fires an event for Enyo to listen for. - dispatch: function(e) { - // Find the control who maps to e.target, or the first control that maps to an ancestor of e.target. - var c = this.findDispatchTarget(e.target) || this.findDefaultTarget(e); - // Cache the original target - e.dispatchTarget = c; - // support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing. - for (var i=0, fn; (fn=this.features[i]); i++) { - if (fn.call(this, e) === true) { - return; - } - } - if (c && !e.preventDispatch) { - this.dispatchBubble(e, c); - } - }, - //* Takes an Event.target and finds the corresponding Enyo control. - findDispatchTarget: function(inNode) { - var t, n = inNode; - // FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context" - // which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if - // it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block. - try { - while (n) { - if ((t = enyo.$[n.id])) { - // there could be multiple nodes with this id, the relevant node for this event is n - // we don't push this directly to t.node because sometimes we are just asking what - // the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut) - t.eventNode = n; - break; - } - n = n.parentNode; - } - } catch(x) { - enyo.log(x, n); - } - return t; - }, - //* Returns the default Enyo control for events. - findDefaultTarget: function(e) { - return enyo.master; - }, - dispatchBubble: function(e, c) { - return c.bubble("on" + e.type, e, c); - } -}; - -// called in the context of an event -enyo.iePreventDefault = function() { - try { - this.returnValue = false; - } - catch(e) { - // do nothing - } -}; - -enyo.dispatch = function(inEvent) { - return enyo.dispatcher.dispatch(inEvent); -}; - -enyo.bubble = function(inEvent) { - // '|| window.event' clause needed for IE8 - var e = inEvent || window.event; - if (e) { - // We depend on e.target existing for event tracking and dispatching. - if (!e.target) { - e.target = e.srcElement; - } - enyo.dispatch(e); - } -}; - -// This string is set on event handlers attributes for DOM elements that -// don't normally bubble (like onscroll) so that they can participate in the -// Enyo event system. -enyo.bubbler = "enyo.bubble(arguments[0])"; - -// The code below helps make Enyo compatible with Google Packages Apps -// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html) -// which, among other things forbids use of inline scripts. -// We replace online scripting with equivalent means, leaving enyo.bubbler -// for backward compatibility. -(function() { - var bubbleUp = function() { - enyo.bubble(arguments[0]); - }; - - /** - * Makes given events bubble on specified enyo contol - */ - enyo.makeBubble = function() { - var args = Array.prototype.slice.call(arguments, 0), - control = args.shift(); - - if((typeof control === "object") && (typeof control.hasNode === "function")) { - enyo.forEach(args, function(event) { - if(this.hasNode()) { - enyo.dispatcher.listen(this.node, event, bubbleUp); - } - }, control); - } - }; -})(); - -// FIXME: we need to create and initialize dispatcher someplace else to allow overrides -enyo.requiresWindow(enyo.dispatcher.connect); - -// generate a tapped event for a raw-click event -enyo.dispatcher.features.push( - function (e) { - if ("click" === e.type) { - if (e.clientX === 0 && e.clientY === 0) { - // this allows the click to dispatch as well - // but note the tap event will fire first - var cp = enyo.clone(e); - cp.type = "tap"; - enyo.dispatch(cp); - } - } - } -); diff --git a/enyo/source/dom/dom.css b/enyo/source/dom/dom.css deleted file mode 100644 index 8fa1232..0000000 --- a/enyo/source/dom/dom.css +++ /dev/null @@ -1,100 +0,0 @@ -/* things we always want */ -body { - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; -} - -/* allow hw-accelerated scrolling on platforms that support it */ -body.webkitOverflowScrolling { - -webkit-overflow-scrolling: touch; -} - -/* for apps */ -.enyo-document-fit { - margin: 0; - height: 100%; - /* note: giving html overflow: auto is odd and was only ever done to avoid duplication - however, android 4.04 sometimes does not hide nodes when their display is set to none - if document is overflow auto. - */ - position: relative; -} - -.enyo-body-fit { - margin: 0; - height: 100%; - /* helps prevent ios page scroll */ - overflow: auto; - position: relative; -} - -.enyo-no-touch-action { - -ms-touch-action: none; -} - -/* reset */ - -button { - font-size: inherit; - font-family: inherit; -} -button::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* user selection */ - -.enyo-unselectable { - cursor: default; - -ms-user-select: none; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; -} - -.enyo-unselectable::selection, .enyo-unselectable ::selection { - color: transparent; -} - -.enyo-selectable { - cursor: auto; - -ms-user-select: element; - -webkit-user-select: text; - -moz-user-select: text; - user-select: text; -} - -.enyo-selectable::selection, .enyo-selectable ::selection { - background: #3297FD; - color: #FFF; -} - -/* layout */ - -body .enyo-fit { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.enyo-clip { - overflow: hidden; -} - -.enyo-border-box { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* compositing */ - -.enyo-composite { - -webkit-transform: translateZ(0); - -moz-transform: translateZ(0); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - transform: translateZ(0); -} diff --git a/enyo/source/dom/dom.js b/enyo/source/dom/dom.js deleted file mode 100644 index 9679b8d..0000000 --- a/enyo/source/dom/dom.js +++ /dev/null @@ -1,231 +0,0 @@ -//* @public - -/** - Allow bootstrapping in environments that do not have a window object right away. -*/ -enyo.requiresWindow = function(inFunction) { - inFunction(); -}; - -enyo.dom = { - /** - Shortcut for _document.getElementById_ if _id_ is a string, otherwise returns _id_. - Uses _window.document_ unless a document is specified in the (optional) _doc_ - parameter. - - // find 'node' if it's a string id, or return it unchanged if it's already a node reference - var domNode = enyo.dom.byId(node); - */ - byId: function(id, doc){ - return (typeof id == "string") ? (doc || document).getElementById(id) : id; - }, - /** - return string with ampersand, less-than, and greater-than characters - replaced with HTML entities, e.g. - - '<code>"This & That"</code>' - - becomes - - '&lt;code&gt;"This &amp; That"&lt;/code&gt;' - */ - escape: function(inText) { - return inText !== null ? String(inText).replace(/&/g,'&').replace(//g,'>') : ''; - }, - /** - Returns an object describing the geometry of this node, like so: - - {left: _offsetLeft_, top: _offsetTop_, width: _offsetWidth_, height: _offsetHeight_} - */ - getBounds: function(n) { - if (n) { - return {left: n.offsetLeft, top: n.offsetTop, width: n.offsetWidth, height: n.offsetHeight}; - } - else { - return null; - } - }, - //* @protected - getComputedStyle: function(inNode) { - return window.getComputedStyle && inNode && window.getComputedStyle(inNode, null); - }, - getComputedStyleValue: function(inNode, inProperty, inComputedStyle) { - var s = inComputedStyle || this.getComputedStyle(inNode); - return s ? s.getPropertyValue(inProperty) : null; - }, - getFirstElementByTagName: function(inTagName) { - var e = document.getElementsByTagName(inTagName); - return e && e[0]; - }, - applyBodyFit: function() { - var h = this.getFirstElementByTagName("html"); - if (h) { - h.className += " enyo-document-fit"; - } - var b = this.getFirstElementByTagName("body"); - if (b) { - b.className += " enyo-body-fit"; - } - enyo.bodyIsFitting = true; - }, - getWindowWidth: function() { - if (window.innerWidth) { - return window.innerWidth; - } - if (document.body && document.body.offsetWidth) { - return document.body.offsetWidth; - } - if (document.compatMode=='CSS1Compat' && - document.documentElement && - document.documentElement.offsetWidth ) { - return document.documentElement.offsetWidth; - } - return 320; - }, - getWindowHeight: function() { - if (window.innerHeight) { - return window.innerHeight; - } - if (document.body && document.body.offsetHeight) { - return document.body.offsetHeight; - } - if (document.compatMode=='CSS1Compat' && - document.documentElement && - document.documentElement.offsetHeight ) { - return document.documentElement.offsetHeight; - } - return 480; - }, - // moved from FittableLayout.js into common protected code - _ieCssToPixelValue: function(inNode, inValue) { - var v = inValue; - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - var s = inNode.style; - // store style and runtime style values - var l = s.left; - var rl = inNode.runtimeStyle && inNode.runtimeStyle.left; - // then put current style in runtime style. - if (rl) { - inNode.runtimeStyle.left = inNode.currentStyle.left; - } - // apply given value and measure its pixel value - s.left = v; - v = s.pixelLeft; - // finally restore previous state - s.left = l; - if (rl) { - s.runtimeStyle.left = rl; - } - return v; - }, - _pxMatch: /px/i, - getComputedBoxValue: function(inNode, inProp, inBoundary, inComputedStyle) { - var s = inComputedStyle || this.getComputedStyle(inNode); - if (s) { - return parseInt(s.getPropertyValue(inProp + "-" + inBoundary), 0); - } else if (inNode && inNode.currentStyle) { - var v = inNode.currentStyle[inProp + enyo.cap(inBoundary)]; - if (!v.match(this._pxMatch)) { - v = this._ieCssToPixelValue(inNode, v); - } - return parseInt(v, 0); - } - return 0; - }, - //* @public - //* Gets the boundaries of a node's margin or padding box. - calcBoxExtents: function(inNode, inBox) { - var s = this.getComputedStyle(inNode); - return { - top: this.getComputedBoxValue(inNode, inBox, "top", s), - right: this.getComputedBoxValue(inNode, inBox, "right", s), - bottom: this.getComputedBoxValue(inNode, inBox, "bottom", s), - left: this.getComputedBoxValue(inNode, inBox, "left", s) - }; - }, - //* Gets the calculated padding of a node. - calcPaddingExtents: function(inNode) { - return this.calcBoxExtents(inNode, "padding"); - }, - //* Gets the calculated margin of a node. - calcMarginExtents: function(inNode) { - return this.calcBoxExtents(inNode, "margin"); - }, - /** - Returns an object like `{top: 0, left: 0, bottom: 100, right: 100, height: 10, width: 10}` - that represents the object's position relative to `relativeToNode` (suitable for absolute - positioning within that parent node). Negative values mean part of the object is not visible. - If you leave `relativeToNode` undefined (or it is not a parent element), then the position - will be relative to the viewport and suitable for absolute positioning in a floating layer. - */ - calcNodePosition: function(inNode, relativeToNode) { - // Parse upward and grab our positioning relative to the viewport - var top = 0, - left = 0, - node = inNode, - width = node.offsetWidth, - height = node.offsetHeight, - transformProp = enyo.dom.getStyleTransformProp(), - xregex = /translateX\((-?\d+)px\)/i, - yregex = /translateY\((-?\d+)px\)/i, - borderLeft = 0, borderTop = 0, - totalHeight = 0, totalWidth = 0; - - if (relativeToNode) { - totalHeight = relativeToNode.offsetHeight; - totalWidth = relativeToNode.offsetWidth; - } else { - totalHeight = (document.body.parentNode.offsetHeight > this.getWindowHeight() ? this.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight); - totalWidth = (document.body.parentNode.offsetWidth > this.getWindowWidth() ? this.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth); - } - - if (node.offsetParent) { - do { - left += node.offsetLeft - (node.offsetParent ? node.offsetParent.scrollLeft : 0); - if (transformProp && xregex.test(node.style[transformProp])) { - left += parseInt(node.style[transformProp].replace(xregex, '$1'), 10); - } - top += node.offsetTop - (node.offsetParent ? node.offsetParent.scrollTop : 0); - if (transformProp && yregex.test(node.style[transformProp])) { - top += parseInt(node.style[transformProp].replace(yregex, '$1'), 10); - } - // Need to correct for borders if any exist on parent elements - if (node !== inNode) { - if (node.currentStyle) { - // Oh IE, we do so love working around your incompatibilities - borderLeft = parseInt(node.currentStyle.borderLeftWidth, 10); - borderTop = parseInt(node.currentStyle.borderTopWidth, 10); - } else if (window.getComputedStyle) { - borderLeft = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-left-width'), 10); - borderTop = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-top-width'), 10); - } else { - // No computed style options, so try the normal style object (much less robust) - borderLeft = parseInt(node.style.borderLeftWidth, 10); - borderTop = parseInt(node.style.borderTopWidth, 10); - } - if (borderLeft) { - left += borderLeft; - } - if (borderTop) { - top += borderTop; - } - } - } while ((node = node.offsetParent) && node !== relativeToNode); - } - return { - 'top': top, - 'left': left, - 'bottom': totalHeight - top - height, - 'right': totalWidth - left - width, - 'height': height, - 'width': width - }; - }, - //* use to modify innerHTML in a manner that's safe for Win8 applications - setInnerHtml: function(node, html) { - enyo.execUnsafeLocalFunction(function() { - node.innerHTML = html; - }); - } -}; diff --git a/enyo/source/dom/drag.js b/enyo/source/dom/drag.js deleted file mode 100644 index e7078ef..0000000 --- a/enyo/source/dom/drag.js +++ /dev/null @@ -1,266 +0,0 @@ -/** - Enyo supports a cross-platform set of drag events. These events allow users - to write a single set of event handlers for applications that run on both - mobile and desktop platforms. - - The following events are provided: - - * "dragstart" - * "dragfinish" - * "drag" - * "drop" - * "dragover" - * "dragout" - * "hold" - * "release" - * "holdpulse" - * "flick" - - For more information on these events, see the documentation on - [User Input](https://github.com/enyojs/enyo/wiki/User-Input) in the Enyo - Developer Guide. -*/ - -//* @protected -enyo.dispatcher.features.push( - function(e) { - // NOTE: beware of properties in enyo.gesture inadvertently mapped to event types - if (enyo.gesture.drag[e.type]) { - return enyo.gesture.drag[e.type](e); - } - } -); - -//* @public -enyo.gesture.drag = { - //* @protected - hysteresisSquared: 16, - holdPulseDelay: 200, - trackCount: 5, - minFlick: 0.1, - minTrack: 8, - down: function(e) { - // tracking if the mouse is down - //enyo.log("tracking ON"); - // Note: 'tracking' flag indicates interest in mousemove, it's turned off - // on mouseup - // make sure to stop dragging in case the up event was not received. - this.stopDragging(e); - this.cancelHold(); - this.target = e.target; - this.startTracking(e); - this.beginHold(e); - }, - move: function(e) { - if (this.tracking) { - this.track(e); - // If the mouse is not down and we're tracking a drag, abort. - // this error condition can occur on IE/Webkit after interaction with a scrollbar. - if (!e.which) { - this.stopDragging(e); - this.cancelHold(); - this.tracking = false; - //enyo.log("enyo.gesture.drag: mouse must be down to drag."); - return; - } - if (this.dragEvent) { - this.sendDrag(e); - } else if (this.dy*this.dy + this.dx*this.dx >= this.hysteresisSquared) { - this.sendDragStart(e); - this.cancelHold(); - } - } - }, - up: function(e) { - this.endTracking(e); - this.stopDragging(e); - this.cancelHold(); - }, - leave: function(e) { - if (this.dragEvent) { - this.sendDragOut(e); - } - }, - stopDragging: function(e) { - if (this.dragEvent) { - this.sendDrop(e); - var handled = this.sendDragFinish(e); - this.dragEvent = null; - return handled; - } - }, - makeDragEvent: function(inType, inTarget, inEvent, inInfo) { - var adx = Math.abs(this.dx), ady = Math.abs(this.dy); - var h = adx > ady; - // suggest locking if off-axis < 22.5 degrees - var l = (h ? ady/adx : adx/ady) < 0.414; - var e = { - type: inType, - dx: this.dx, - dy: this.dy, - ddx: this.dx - this.lastDx, - ddy: this.dy - this.lastDy, - xDirection: this.xDirection, - yDirection: this.yDirection, - pageX: inEvent.pageX, - pageY: inEvent.pageY, - clientX: inEvent.clientX, - clientY: inEvent.clientY, - horizontal: h, - vertical: !h, - lockable: l, - target: inTarget, - dragInfo: inInfo, - ctrlKey: inEvent.ctrlKey, - altKey: inEvent.altKey, - metaKey: inEvent.metaKey, - shiftKey: inEvent.shiftKey, - srcEvent: inEvent.srcEvent - }; - //Fix for IE8, which doesn't include pageX and pageY properties - if(enyo.platform.ie==8 && e.target) { - e.pageX = e.clientX + e.target.scrollLeft; - e.pageY = e.clientY + e.target.scrollTop; - } - e.preventDefault = enyo.gesture.preventDefault; - e.disablePrevention = enyo.gesture.disablePrevention; - return e; - }, - sendDragStart: function(e) { - //enyo.log("dragstart"); - this.dragEvent = this.makeDragEvent("dragstart", this.target, e); - enyo.dispatch(this.dragEvent); - }, - sendDrag: function(e) { - //enyo.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id); - // send dragOver event to the standard event target - var synth = this.makeDragEvent("dragover", e.target, e, this.dragEvent.dragInfo); - enyo.dispatch(synth); - // send drag event to the drag source - synth.type = "drag"; - synth.target = this.dragEvent.target; - enyo.dispatch(synth); - }, - sendDragFinish: function(e) { - //enyo.log("dragfinish"); - var synth = this.makeDragEvent("dragfinish", this.dragEvent.target, e, this.dragEvent.dragInfo); - synth.preventTap = function() { - if (e.preventTap) { - e.preventTap(); - } - }; - enyo.dispatch(synth); - }, - sendDragOut: function(e) { - var synth = this.makeDragEvent("dragout", e.target, e, this.dragEvent.dragInfo); - enyo.dispatch(synth); - }, - sendDrop: function(e) { - var synth = this.makeDragEvent("drop", e.target, e, this.dragEvent.dragInfo); - synth.preventTap = function() { - if (e.preventTap) { - e.preventTap(); - } - }; - enyo.dispatch(synth); - }, - startTracking: function(e) { - this.tracking = true; - // note: use clientX/Y to be compatible with ie8 - this.px0 = e.clientX; - this.py0 = e.clientY; - this.flickInfo = {startEvent: e, moves: []}; - this.track(e); - }, - track: function(e) { - this.lastDx = this.dx; - this.lastDy = this.dy; - this.dx = e.clientX - this.px0; - this.dy = e.clientY - this.py0; - this.xDirection = this.calcDirection(this.dx - this.lastDx, 0); - this.yDirection = this.calcDirection(this.dy - this.lastDy, 0); - // - var ti = this.flickInfo; - ti.moves.push({ - x: e.clientX, - y: e.clientY, - t: enyo.now() - }); - // track specified # of points - if (ti.moves.length > this.trackCount) { - ti.moves.shift(); - } - }, - endTracking: function(e) { - this.tracking = false; - var ti = this.flickInfo; - var moves = ti && ti.moves; - if (moves && moves.length > 1) { - // note: important to use up time to reduce flick - // velocity based on time between move and up. - var l = moves[moves.length-1]; - var n = enyo.now(); - // take the greatest of flick between each tracked move and last move - for (var i=moves.length-2, dt=0, x1=0, y1=0, x=0, y=0, sx=0, sy=0, m; (m=moves[i]); i--) { - // this flick (this move - last move) / (this time - last time) - dt = n - m.t; - x1 = (l.x - m.x) / dt; - y1 = (l.y - m.y) / dt; - // establish flick direction - sx = sx || (x1 < 0 ? -1 : (x1 > 0 ? 1 : 0)); - sy = sy || (y1 < 0 ? -1 : (y1 > 0 ? 1 : 0)); - // if either axis is a greater flick than previously recorded use this one - if ((x1 * sx > x * sx) || (y1 * sy > y * sy)) { - x = x1; - y = y1; - } - } - var v = Math.sqrt(x*x + y*y); - if (v > this.minFlick) { - // generate the flick using the start event so it has those coordinates - this.sendFlick(ti.startEvent, x, y, v); - } - } - this.flickInfo = null; - }, - calcDirection: function(inNum, inDefault) { - return inNum > 0 ? 1 : (inNum < 0 ? -1 : inDefault); - }, - beginHold: function(e) { - this.holdStart = enyo.now(); - this.holdJob = setInterval(enyo.bind(this, "sendHoldPulse", e), this.holdPulseDelay); - }, - cancelHold: function() { - clearInterval(this.holdJob); - this.holdJob = null; - if (this.sentHold) { - this.sentHold = false; - this.sendRelease(this.holdEvent); - } - }, - sendHoldPulse: function(inEvent) { - if (!this.sentHold) { - this.sentHold = true; - this.sendHold(inEvent); - } - var e = enyo.gesture.makeEvent("holdpulse", inEvent); - e.holdTime = enyo.now() - this.holdStart; - enyo.dispatch(e); - }, - sendHold: function(inEvent) { - this.holdEvent = inEvent; - var e = enyo.gesture.makeEvent("hold", inEvent); - enyo.dispatch(e); - }, - sendRelease: function(inEvent) { - var e = enyo.gesture.makeEvent("release", inEvent); - enyo.dispatch(e); - }, - sendFlick: function(inEvent, inX, inY, inV) { - var e = enyo.gesture.makeEvent("flick", inEvent); - e.xVelocity = inX; - e.yVelocity = inY; - e.velocity = inV; - enyo.dispatch(e); - } -}; \ No newline at end of file diff --git a/enyo/source/dom/gesture.js b/enyo/source/dom/gesture.js deleted file mode 100644 index 5038fc2..0000000 --- a/enyo/source/dom/gesture.js +++ /dev/null @@ -1,172 +0,0 @@ -//* @public -/** - Enyo supports a set of normalized events that work similarly across all - supported platforms. These events are provided so that users can write a - single set of event handlers for applications that run on both mobile and - desktop platforms. They are needed because desktop and mobile platforms - handle basic input differently. - - For more information on normalized input events and their associated - properties, see the documentation on - [User Input](https://github.com/enyojs/enyo/wiki/User-Input) in the Enyo - Developer Guide. -*/ -enyo.gesture = { - //* @protected - eventProps: ["target", "relatedTarget", "clientX", "clientY", "pageX", "pageY", - "screenX", "screenY", "altKey", "ctrlKey", "metaKey", "shiftKey", - "detail", "identifier", "dispatchTarget", "which", "srcEvent"], - makeEvent: function(inType, inEvent) { - var e = {type: inType}; - for (var i=0, p; (p=this.eventProps[i]); i++) { - e[p] = inEvent[p]; - } - e.srcEvent = e.srcEvent || inEvent; - e.preventDefault = this.preventDefault; - e.disablePrevention = this.disablePrevention; - // - // normalize event.which and event.pageX/event.pageY - // Note that while "which" works in IE9, it is broken for mousemove. Therefore, - // in IE, use window.event.button - if (enyo.platform.ie < 10) { - //Fix for IE8, which doesn't include pageX and pageY properties - if(enyo.platform.ie==8 && e.target) { - e.pageX = e.clientX + e.target.scrollLeft; - e.pageY = e.clientY + e.target.scrollTop; - } - var b = window.event && window.event.button; - // multi-button not supported, priority: left, right, middle - // (note: IE bitmask is 1=left, 2=right, 4=center); - e.which = b & 1 ? 1 : (b & 2 ? 2 : (b & 4 ? 3 : 0)); - } else if (enyo.platform.webos || window.PalmSystem) { - // Temporary fix for owos: it does not currently supply 'which' on move events - // and the user agent string doesn't identify itself so we test for PalmSystem - if (e.which === 0) { - e.which = 1; - } - } - return e; - }, - down: function(inEvent) { - // cancel any hold since it's possible in corner cases to get a down without an up - var e = this.makeEvent("down", inEvent); - enyo.dispatch(e); - this.downEvent = e; - }, - move: function(inEvent) { - var e = this.makeEvent("move", inEvent); - // include delta and direction v. down info in move event - e.dx = e.dy = e.horizontal = e.vertical = 0; - if (e.which && this.downEvent) { - e.dx = inEvent.clientX - this.downEvent.clientX; - e.dy = inEvent.clientY - this.downEvent.clientY; - e.horizontal = Math.abs(e.dx) > Math.abs(e.dy); - e.vertical = !e.horizontal; - } - enyo.dispatch(e); - }, - up: function(inEvent) { - var e = this.makeEvent("up", inEvent); - var tapPrevented = false; - e.preventTap = function() { - tapPrevented = true; - }; - enyo.dispatch(e); - if (!tapPrevented && this.downEvent && this.downEvent.which == 1) { - this.sendTap(e); - } - this.downEvent = null; - }, - over: function(inEvent) { - enyo.dispatch(this.makeEvent("enter", inEvent)); - }, - out: function(inEvent) { - enyo.dispatch(this.makeEvent("leave", inEvent)); - }, - sendTap: function(inEvent) { - // The common ancestor for the down/up pair is the origin for the tap event - var t = this.findCommonAncestor(this.downEvent.target, inEvent.target); - if (t) { - var e = this.makeEvent("tap", inEvent); - e.target = t; - enyo.dispatch(e); - } - }, - findCommonAncestor: function(inA, inB) { - var p = inB; - while (p) { - if (this.isTargetDescendantOf(inA, p)) { - return p; - } - p = p.parentNode; - } - }, - isTargetDescendantOf: function(inChild, inParent) { - var c = inChild; - while(c) { - if (c == inParent) { - return true; - } - c = c.parentNode; - } - } -}; - -//* @protected - -// installed on events and called in event context -enyo.gesture.preventDefault = function() { - if (this.srcEvent) { - this.srcEvent.preventDefault(); - } -}; - -enyo.gesture.disablePrevention = function() { - this.preventDefault = enyo.nop; - if (this.srcEvent) { - this.srcEvent.preventDefault = enyo.nop; - } -}; - -enyo.dispatcher.features.push( - function(e) { - // NOTE: beware of properties in enyo.gesture inadvertently mapped to event types - if (enyo.gesture.events[e.type]) { - return enyo.gesture.events[e.type](e); - } - } -); - -enyo.gesture.events = { - mousedown: function(e) { - enyo.gesture.down(e); - }, - mouseup: function(e) { - enyo.gesture.up(e); - }, - mousemove: function(e) { - enyo.gesture.move(e); - }, - mouseover: function(e) { - enyo.gesture.over(e); - }, - mouseout: function(e) { - enyo.gesture.out(e); - } -}; - -// Firefox mousewheel handling -enyo.requiresWindow(function() { - if (document.addEventListener) { - document.addEventListener("DOMMouseScroll", function(inEvent) { - var e = enyo.clone(inEvent); - e.preventDefault = function() { - inEvent.preventDefault(); - }; - e.type = "mousewheel"; - var p = e.VERTICAL_AXIS == e.axis ? "wheelDeltaY" : "wheelDeltaX"; - e[p] = e.detail * -40; - enyo.dispatch(e); - }, false); - } -}); diff --git a/enyo/source/dom/modal.js b/enyo/source/dom/modal.js deleted file mode 100644 index dea4a9e..0000000 --- a/enyo/source/dom/modal.js +++ /dev/null @@ -1,49 +0,0 @@ -//* @protected - -/** - Event modal capture feature: capture events to a specific - control via enyo.dispatcher.capture(inControl, inShouldForward) - release events via enyo.dispatcher.release() -*/ -enyo.dispatcher.features.push(function(e) { - var c = e.dispatchTarget; - var wants = this.captureTarget && !this.noCaptureEvents[e.type]; - var needs = wants && !(c && c.isDescendantOf && c.isDescendantOf(this.captureTarget)); - if (needs) { - var c1 = e.captureTarget = this.captureTarget; - // NOTE: We do not want releasing capture while an event is being processed to alter - // the way the event propagates. Therefore decide if the event should forward - // before the capture target receives the event (since it may release capture). - var shouldForward = (this.autoForwardEvents[e.type] || this.forwardEvents); - this.dispatchBubble(e, c1); - if (!shouldForward) { - e.preventDispatch = true; - } - } -}); - -// -// NOTE: This object is a plug-in; these methods should -// be called on _enyo.dispatcher_, and not on the plug-in itself. -// -enyo.mixin(enyo.dispatcher, { - noCaptureEvents: {load: 1, unload:1, error: 1}, - autoForwardEvents: {leave: 1, resize: 1}, - captures: [], - //* Capture events for `inTarget` and optionally forward them - capture: function(inTarget, inShouldForward) { - var info = {target: inTarget, forward: inShouldForward}; - this.captures.push(info); - this.setCaptureInfo(info); - }, - //* Release the last captured event - release: function() { - this.captures.pop(); - this.setCaptureInfo(this.captures[this.captures.length-1]); - }, - //* Set the information for a captured event - setCaptureInfo: function(inInfo) { - this.captureTarget = inInfo && inInfo.target; - this.forwardEvents = inInfo && inInfo.forward; - } -}); diff --git a/enyo/source/dom/package.js b/enyo/source/dom/package.js deleted file mode 100644 index d087236..0000000 --- a/enyo/source/dom/package.js +++ /dev/null @@ -1,15 +0,0 @@ -enyo.depends( - "dom.css", - "dom.js", - "transform.js", - "Control.js", - "platform.js", - "animation.js", - "phonegap.js", - "dispatcher.js", - "preview.js", - "modal.js", - "gesture.js", - "drag.js", - "transition.js" -); diff --git a/enyo/source/dom/phonegap.js b/enyo/source/dom/phonegap.js deleted file mode 100644 index da86f71..0000000 --- a/enyo/source/dom/phonegap.js +++ /dev/null @@ -1,46 +0,0 @@ -/** -Listens for PhoneGap specific events - -Events are exposed through the [Signals](#enyo.Signals) kind by adding callback handlers. - -Example: - -enyo.kind({ - name: "App", - components: [ - {kind: "Signals", ondeviceready: "deviceready"}, - ... - ], - deviceready: function() { - // PhoneGap API exists at this point forward - } -}); - -List of PhoneGap events detailed on the [PhoneGap Docs](http://docs.phonegap.com/en/1.6.0/phonegap_events_events.md.html#Events) -*/ -//* @protected -(function(){ - if (window.cordova || window.PhoneGap) { - var pge = [ - "deviceready", - "pause", - "resume", - "online", - "offline", - "backbutton", - "batterycritical", - "batterylow", - "batterystatus", - "menubutton", - "searchbutton", - "startcallbutton", - "endcallbutton", - "volumedownbutton", - "volumeupbutton" - ]; - for (var i=0, e; (e=pge[i]); i++) { - // some phonegap events have no type, so enyo.dispatch fails - document.addEventListener(e, enyo.bind(enyo.Signals, "send", "on" + e), false); - } - } -})(); diff --git a/enyo/source/dom/platform.js b/enyo/source/dom/platform.js deleted file mode 100644 index d03f392..0000000 --- a/enyo/source/dom/platform.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - Determines OS versions of platforms that need special treatment. - Can have one of the following properties: - - * android - * androidChrome (Chrome on Android, standard starting in 4.1) - * androidFirefox - * ie - * ios - * webos - * blackberry - * safari (desktop version) - * chrome (desktop version) - * firefox (desktop version) - - If the property is defined, its value will be the major version number - of the platform. - - Example: - - // android 2 does not have 3d css - if (enyo.platform.android < 3) { - t = "translate(30px, 50px)"; - } else { - t = "translate3d(30px, 50px, 0)"; - } - this.applyStyle("-webkit-transform", t); -*/ -enyo.platform = { - //* True if the platform has native single finger events - touch: Boolean(("ontouchstart" in window) || window.navigator.msMaxTouchPoints), - //* True if the platform has native double finger events - gesture: Boolean(("ongesturestart" in window) || window.navigator.msMaxTouchPoints) -}; - -//* @protected -(function() { - var ua = navigator.userAgent; - var ep = enyo.platform; - var platforms = [ - // Android 4+ using Chrome - {platform: "androidChrome", regex: /Android .* Chrome\/(\d+)[.\d]+/}, - // Android 2 - 4 - {platform: "android", regex: /Android (\d+)/}, - // Kindle Fire - // Force version to 2, (desktop mode does not list android version) - {platform: "android", regex: /Silk\/1./, forceVersion: 2, extra: {silk: 1}}, - // Kindle Fire HD - // Force version to 4 - {platform: "android", regex: /Silk\/2./, forceVersion: 4, extra: {silk: 2}}, - // Windows Phone 7 - 8 - {platform: "windowsPhone", regex: /Windows Phone (?:OS )?(\d+)[.\d]+/}, - // IE 8 - 10 - {platform: "ie", regex: /MSIE (\d+)/}, - // iOS 3 - 5 - // Apple likes to make this complicated - {platform: "ios", regex: /iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/}, - // webOS 1 - 3 - {platform: "webos", regex: /(?:web|hpw)OS\/(\d+)/}, - // desktop Safari - {platform: "safari", regex: /Version\/(\d+)[.\d]+\s+Safari/}, - // desktop Chrome - {platform: "chrome", regex: /Chrome\/(\d+)[.\d]+/}, - // Firefox on Android - {platform: "androidFirefox", regex: /Android;.*Firefox\/(\d+)/}, - // FirefoxOS - {platform: "firefoxOS", regex: /Mobile;.*Firefox\/(\d+)/}, - // desktop Firefox - {platform: "firefox", regex: /Firefox\/(\d+)/}, - // Blackberry 10+ - {platform: "blackberry", regex: /BB1\d;.*Version\/(\d+\.\d+)/} - ]; - for (var i = 0, p, m, v; (p = platforms[i]); i++) { - m = p.regex.exec(ua); - if (m) { - if (p.forceVersion) { - v = p.forceVersion; - } else { - v = Number(m[1]); - } - ep[p.platform] = v; - if (p.extra) { - enyo.mixin(ep, p.extra); - } - break; - } - } - // these platforms only allow one argument for console.log - enyo.dumbConsole = Boolean(ep.android || ep.ios || ep.webos); -})(); \ No newline at end of file diff --git a/enyo/source/dom/preview.js b/enyo/source/dom/preview.js deleted file mode 100644 index 4ed1fca..0000000 --- a/enyo/source/dom/preview.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - Dispatcher preview feature: allow control ancestors of the event - target a chance (eldest first) to react via implementing "previewDomEvent." -*/ -//* @protected -(function() { - var fn = "previewDomEvent"; - // - var preview = { - feature: function(e) { - preview.dispatch(e, e.dispatchTarget); - }, - dispatch: function(e, c) { - var l$ = this.buildLineage(c); - // handlers return true to abort preview and prevent default event processing. - for (var i=0, l; (l=l$[i]); i++) { - if (l[fn] && l[fn](e) === true) { - e.preventDispatch = true; - return; - } - } - }, - // we ascend making a list of enyo controls - // NOTE: the control is considered its own ancestor - buildLineage: function(inControl) { - var l = [], c = inControl; - while (c) { - l.unshift(c); - c = c.parent; - } - return l; - } - }; - // - enyo.dispatcher.features.push(preview.feature); -})(); \ No newline at end of file diff --git a/enyo/source/dom/transform.js b/enyo/source/dom/transform.js deleted file mode 100644 index b42a342..0000000 --- a/enyo/source/dom/transform.js +++ /dev/null @@ -1,139 +0,0 @@ -//* @protected -(function() { - enyo.dom.calcCanAccelerate = function() { - /* Android 2 is a liar: it does NOT support 3D transforms, even though Perspective is the best check */ - if (enyo.platform.android <= 2) { - return false; - } - var p$ = ["perspective", "WebkitPerspective", "MozPerspective", "msPerspective", "OPerspective"]; - for (var i=0, p; (p=p$[i]); i++) { - if (typeof document.body.style[p] != "undefined") { - return true; - } - } - return false; - }; - var cssTransformProps = ["transform", "-webkit-transform", "-moz-transform", "-ms-transform", "-o-transform"]; - var styleTransformProps = ["transform", "webkitTransform", "MozTransform", "msTransform", "OTransform"]; - enyo.dom.getCssTransformProp = function() { - if (this._cssTransformProp) { - return this._cssTransformProp; - } - var i = enyo.indexOf(this.getStyleTransformProp(), styleTransformProps); - return this._cssTransformProp = cssTransformProps[i]; - }; - enyo.dom.getStyleTransformProp = function() { - if (this._styleTransformProp || !document.body) { - return this._styleTransformProp; - } - for (var i = 0, p; (p = styleTransformProps[i]); i++) { - if (typeof document.body.style[p] != "undefined") { - return this._styleTransformProp = p; - } - } - }; - enyo.dom.domTransformsToCss = function(inTransforms) { - var n, v, text = ''; - for (n in inTransforms) { - v = inTransforms[n]; - if ((v !== null) && (v !== undefined) && (v !== "")) { - text += n + '(' + v + ') '; - } - } - return text; - }; - enyo.dom.transformsToDom = function(inControl) { - var t = this.domTransformsToCss(inControl.domTransforms); - var st = inControl.hasNode() ? inControl.node.style : null; - var ds = inControl.domStyles; - var sp = this.getStyleTransformProp(); - var cp = this.getCssTransformProp(); - if (sp && cp) { - ds[cp] = t; - if (st) { - st[sp] = t; - } else { - inControl.domStylesChanged(); - } - } - }; - //* @public - /** - Returns true if the platform supports CSS3 Transforms - */ - enyo.dom.canTransform = function() { - return Boolean(this.getStyleTransformProp()); - }; - /** - Returns true if platform supports CSS3 3D Transforms. - - Typically used like this: - - if (enyo.dom.canAccelerate()) { - enyo.dom.transformValue(this.$.slidingThing, "translate3d", x + "," + y + "," + "0") - } else { - enyo.dom.transformValue(this.$.slidingThing, "translate", x + "," + y); - } - - */ - enyo.dom.canAccelerate = function() { - return this.accelerando !== undefined ? this.accelerando: document.body && (this.accelerando = this.calcCanAccelerate()); - }; - /** - Applies a series of transforms to _inControl_, using the platform's prefixed transform property. - - **Note:** Transforms are not commutative, so order is important - - Transform values are updated by successive calls: - - enyo.dom.transform(control, {translate: "30px, 40px", scale: 2, rotate: "20deg"}); - enyo.dom.transform(control, {scale: 3, skewX: "-30deg"}); - - is equivalent to: - - enyo.dom.transform(control, {translate: "30px, 40px", scale: 3, rotate: "20deg", skewX: "-30deg"}); - - When applying these transforms in webkit browser, this is equivalent to: - - control.applyStyle("-webkit-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)"); - - And in firefox, this is equivalent to: - - control.applyStyle("-moz-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)"); - - */ - enyo.dom.transform = function(inControl, inTransforms) { - var d = inControl.domTransforms = inControl.domTransforms || {}; - enyo.mixin(d, inTransforms); - this.transformsToDom(inControl); - }; - - /** - Apply a single transform to _inControl_. - - Example: - - tap: function(inSender, inEvent) { - var c = inEvent.originator; - var r = c.rotation || 0; - r = (r + 45) % 360; - c.rotation = r; - enyo.dom.transformValue(c, "rotate", r); - } - - This will rotate the tapped control by 45 degrees clockwise. - */ - enyo.dom.transformValue = function(inControl, inTransform, inValue) { - var d = inControl.domTransforms = inControl.domTransforms || {}; - d[inTransform] = inValue; - this.transformsToDom(inControl); - }; - //* @protected - /** - Applies a transform that should trigger GPU compositing for _inControl_ - */ - enyo.dom.accelerate = function(inControl, inValue) { - var v = inValue == "auto" ? this.canAccelerate() : inValue; - this.transformValue(inControl, "translateZ", v ? 0 : null); - }; -})(); diff --git a/enyo/source/dom/transition.js b/enyo/source/dom/transition.js deleted file mode 100644 index 33affd0..0000000 --- a/enyo/source/dom/transition.js +++ /dev/null @@ -1,5 +0,0 @@ -enyo.dom.transition = (enyo.platform.ios || enyo.platform.android || enyo.platform.chrome || enyo.platform.androidChrome || enyo.platform.safari) - ? "-webkit-transition" - : (enyo.platform.firefox || enyo.platform.firefoxOS || enyo.platform.androidFirefox) - ? "-moz-transition" - : "transition"; \ No newline at end of file diff --git a/enyo/source/kernel/Component.js b/enyo/source/kernel/Component.js deleted file mode 100644 index edcd9d5..0000000 --- a/enyo/source/kernel/Component.js +++ /dev/null @@ -1,547 +0,0 @@ -/** - _enyo.Component_ is the fundamental building block for Enyo applications. - Components are designed to fit together, so that complex behaviors may be - fashioned from smaller bits of functionality. - - Component constructors take a single argument (sometimes called a - _Component configuration_), a JavaScript object that defines various - properties to be initialized on the Component. For example: - - // create a new component, initialize its name property to 'me'. - var c = new enyo.Component({ - name: "me" - }); - - When a Component is instantiated, items configured in its _components_ - property are instantiated, too: - - // create a new component, which itself has a component - var c = new enyo.Component({ - name: "me", - components: [ - {kind: "Component", name: "other"} - ] - }); - - In this case, when _me_ is created, _other_ is also created, and we say that - _me owns other_. In other words, the _owner_ property of _other_ equals - _me_. Notice that you can specify the _kind_ of _other_ explicitly in its - configuration block, to tell _me_ what constructor to use to create _other_. - - Note that _kind_ values may be references to actual kinds or string-names of - kinds. Kind names that do not resolve directly to kinds are looked up in - default namespaces. In this case, _kind: "Component"_ resolves to - _enyo.Component_. - - To move a component, use the _setOwner_ method to change the component's owner. - If you want to make a component unowned, use _setOwner(null)_. - - If you make changes to _enyo.Component_, be sure to add or update the - appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). - - For more information, see the documentation on - [Components](https://github.com/enyojs/enyo/wiki/Creating-Components) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Component", - kind: enyo.Object, - published: { - /** - A unique name for the component within its owner. This is used to - set the access name in the owner's _$_ hash. If not specified, a - default name will be provided based on the name of the object's - kind, optionally with a number suffix if more than one instance - exists in the owner. - */ - name: "", - /** - A unique id for the component, usually automatically generated based - on its position within the component hierarchy, although it may also - be directly specified. _enyo.Control_ uses this id value for the DOM - id attribute. - */ - id: "", - /** - The component that owns this component. It is usually implicitly - defined during creation based on the _createComponent_ call or - _components_ hash. - */ - owner: null - }, - //* @protected - statics: { - // for memoizing kind-prefix names in nameComponent - _kindPrefixi: {}, - // for naming the unnamed - _unnamedKindNumber: 0 - }, - defaultKind: "Component", - handlers: {}, - toString: function() { - return this.kindName; - }, - constructor: function() { - // initialize instance objects - this._componentNameMap = {}; - this.$ = {}; - this.inherited(arguments); - }, - constructed: function(inProps) { - // entire constructor chain has fired, now start creation chain - // process instance properties - this.importProps(inProps); - // perform initialization - this.create(); - }, - //* @protected - importProps: function(inProps) { - if (inProps) { - for (var n in inProps) { - this[n] = inProps[n]; - } - } - this.handlers = enyo.mixin(enyo.clone(this.kindHandlers), this.handlers); - }, - create: function() { - this.ownerChanged(); - this.initComponents(); - }, - initComponents: function() { - // The _components_ property in kind declarations is renamed to - // _kindComponents_ by the Component subclass mechanism. This makes it - // easy for the developer to distinguish kindComponents from the components - // in _this.components_, without having to worry about the actual difference. - // - // Specifically, the difference is that kindComponents are constructed as - // owned by this control (whereas components in _this.components_ are not). - // In addition, kindComponents are marked with the _isChrome: true_ flag. - this.createChrome(this.kindComponents); - this.createClientComponents(this.components); - }, - createChrome: function(inComponents) { - this.createComponents(inComponents, {isChrome: true}); - }, - createClientComponents: function(inComponents) { - this.createComponents(inComponents, {owner: this.getInstanceOwner()}); - }, - getInstanceOwner: function() { - return (!this.owner || this.owner.notInstanceOwner) ? this : this.owner; - }, - //* @public - /** - Removes this component from its owner (sets _owner_ to null) and does - any cleanup. The component is flagged with a _destroyed: true_ property. - Usually the component will be suitable for garbage collection after - being destroyed, unless user code keeps a reference to it. - */ - destroy: function() { - this.destroyComponents(); - this.setOwner(null); - // JS objects are never truly destroyed (GC'd) until all references are gone, - // we might have some delayed action on this object that needs to have access - // to this flag. - this.destroyed = true; - }, - /** - Destroys all owned components. - */ - destroyComponents: function() { - enyo.forEach(this.getComponents(), function(c) { - // This local components list may be stale as components - // we owned when the loop started could have been destroyed - // by containers. Avoid redestroying components by testing - // destroyed flag. - if (!c.destroyed) { - c.destroy(); - } - }); - }, - //* @protected - makeId: function() { - var delim = "_", pre = this.owner && this.owner.getId(); - var baseName = this.name || ("@@" + (++enyo.Component._unnamedKindNumber)); - return (pre ? pre + delim : "") + baseName; - }, - ownerChanged: function(inOldOwner) { - if (inOldOwner) { - inOldOwner.removeComponent(this); - } - if (this.owner) { - this.owner.addComponent(this); - } - if (!this.id) { - this.id = this.makeId(); - } - //this.id = this.makeId(); - }, - nameComponent: function(inComponent) { - var prefix = enyo.Component.prefixFromKindName(inComponent.kindName); - // get last memoized name index - var n, i = this._componentNameMap[prefix] || 0; - // find an available name - do { - n = prefix + (++i > 1 ? String(i) : ""); - } while (this.$[n]); - // memoize next likely-unique id tag for this prefix - this._componentNameMap[prefix] = Number(i); - // set and return - return inComponent.name = n; - }, - /** - Adds _inComponent_ to the list of components owned by the current - component (i.e., _this.$_). - */ - addComponent: function(inComponent) { - var n = inComponent.getName(); - if (!n) { - n = this.nameComponent(inComponent); - } - if (this.$[n]) { - this.warn('Duplicate component name "' + n + '" in owner "' + this.id + '" violates ' + - 'unique-name-under-owner rule, replacing existing component in the hash and continuing, ' + - 'but this is an error condition and should be fixed.'); - } - this.$[n] = inComponent; - }, - //* Removes _inComponent_ from the list of components owned by the current - //* component (i.e., _this.$_). - removeComponent: function(inComponent) { - delete this.$[inComponent.getName()]; - }, - //* @public - /** - Returns an array of owned components; in other words, converts the _$_ - hash into an array and returns the array. - */ - getComponents: function() { - var results = []; - for (var n in this.$) { - results.push(this.$[n]); - } - return results; - }, - //* @protected - adjustComponentProps: function(inProps) { - if (this.defaultProps) { - enyo.mixin(inProps, this.defaultProps); - } - inProps.kind = inProps.kind || inProps.isa || this.defaultKind; - inProps.owner = inProps.owner || this; - }, - _createComponent: function(inInfo, inMoreInfo) { - if (!inInfo.kind && ("kind" in inInfo)) { - throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + inInfo.name + "]."; - } - // CAVEAT: inInfo and inMoreInfo are copied before mutation, but it's only a shallow copy - var props = enyo.mixin(enyo.clone(inMoreInfo), inInfo); - this.adjustComponentProps(props); - return enyo.Component.create(props); - }, - //* @public - /** - Creates and returns a component as defined by the combination of - _inInfo_ and _inMoreInfo_. Properties in _inInfo_ override properties in - _inMoreInfo_. - - The created component passes through initialization machinery provided - by the creating component, which may supply special handling. - Unless the owner is explicitly specified, the new component will be - owned by the instance on which _createComponent_ is called. - - // Create a new component named _dynamic_ owned by _this_ - // (will be available as this.$.dynamic). - this.createComponent({name: "dynamic"}); - - // Create a new component named _another_ owned by _other_ - // (will be available as other.$.another). - this.createComponent({name: "another"}, {owner: other}); - */ - createComponent: function(inInfo, inMoreInfo) { - // createComponent and createComponents both delegate to the protected method (_createComponent), - // allowing overrides to customize createComponent and createComponents separately. - return this._createComponent(inInfo, inMoreInfo); - }, - /** - Creates Components as defined by the array of configurations _inInfos_. - Each configuration in _inInfos_ is combined with _inCommonInfo_ as - described in _createComponent_. - - _createComponents_ returns an array of references to the created components. - - // ask foo to create components _bar_ and _zot_, but set the owner of - // both components to _this_. - this.$.foo.createComponents([ - {name: "bar"}, - {name: "zot"} - ], {owner: this}); - */ - createComponents: function(inInfos, inCommonInfo) { - if (inInfos) { - var cs = []; - for (var i=0, ci; (ci=inInfos[i]); i++) { - cs.push(this._createComponent(ci, inCommonInfo)); - } - return cs; - } - }, - //* @protected - getBubbleTarget: function() { - return this.owner; - }, - //* @public - /** - Bubbles an event up an object chain, starting with _this_. - - If a handler for this event returns true (aka _handled_), - bubbling is stopped. - - Handlers always have this signature: - - function(inSender, inEvent) - - where _inSender_ refers to the Component that most recently - propagated the event and _inEvent_ is an object containing - event information. - - _inEvent_ will have at least one property, _originator_, which - references the component that triggered the event in the first place. - */ - bubble: function(inEventName, inEvent, inSender) { - var e = inEvent || {}; - // FIXME: is this the right place? - if (!("originator" in e)) { - e.originator = inSender || this; - // FIXME: use indirection here? - //e.delegate = e.originator.delegate || e.originator.owner; - } - return this.dispatchBubble(inEventName, e, inSender); - }, - /** - Bubbles an event up an object chain, starting above _this_. - - If a handler for this event returns true (aka _handled_), - bubbling is stopped. - - Handlers always have this signature: - - function(inSender, inEvent) - - where _inSender_ refers to the Component that most recently - propagated the event and _inEvent_ is an object containing - event information. - - _inEvent_ will have at least one property, _originator_, which - references the component that triggered the event in the first place. - */ - bubbleUp: function(inEventName, inEvent, inSender) { - // Bubble to next target - var next = this.getBubbleTarget(); - if (next) { - return next.dispatchBubble(inEventName, inEvent, this); - } - return false; - }, - //* @protected - /** - Dispatching refers to sending an event to a named delegate. - This object may dispatch an event to itself via a handler, - or to its owner via an event property, e.g.: - - handlers { - // 'tap' events dispatched to this.tapHandler - ontap: "tapHandler" - } - - // 'tap' events dispatched to 'tapHandler' delegate in this.owner - ontap: "tapHandler" - */ - dispatchEvent: function(inEventName, inEvent, inSender) { - // bottleneck event decoration - this.decorateEvent(inEventName, inEvent, inSender); - // - // Note: null checks and sub-expressions are unrolled in this - // high frequency method to reduce call stack in the 90% case. - // These expressions should fail early. - // - // try to dispatch this event directly via handlers - // - if (this.handlers[inEventName] && this.dispatch(this.handlers[inEventName], inEvent, inSender)) { - return true; - } - // - // try to delegate this event to our owner via event properties - // - if (this[inEventName]) { - return this.bubbleDelegation(this.owner, this[inEventName], inEventName, inEvent, this); - } - }, - // internal - try dispatching event to self, if that fails bubble it up the tree - dispatchBubble: function(inEventName, inEvent, inSender) { - // Try to dispatch from here, stop bubbling on truthy return value - if (this.dispatchEvent(inEventName, inEvent, inSender)) { - return true; - } - // Bubble to next target - return this.bubbleUp(inEventName, inEvent, inSender); - }, - decorateEvent: function(inEventName, inEvent, inSender) { - // an event may float by us as part of a dispatchEvent chain or delegateEvent - // both call this method so intermediaries can decorate inEvent - }, - bubbleDelegation: function(inDelegate, inName, inEventName, inEvent, inSender) { - // next target in bubble sequence - var next = this.getBubbleTarget(); - if (next) { - return next.delegateEvent(inDelegate, inName, inEventName, inEvent, inSender); - } - }, - delegateEvent: function(inDelegate, inName, inEventName, inEvent, inSender) { - // override this method to play tricks with delegation - // bottleneck event decoration - this.decorateEvent(inEventName, inEvent, inSender); - // by default, dispatch this event if we are in fact the delegate - if (inDelegate == this) { - return this.dispatch(inName, inEvent, inSender); - } - return this.bubbleDelegation(inDelegate, inName, inEventName, inEvent, inSender); - }, - //* @public - /** - Dispatches the event to named delegate _inMethodName_, if it exists. - Subkinds may re-route dispatches. - Note that both 'handlers' events and events delegated from owned controls - arrive here. If you need to handle these differently, you may - need to also override _dispatchEvent_. - */ - dispatch: function(inMethodName, inEvent, inSender) { - var fn = inMethodName && this[inMethodName]; - if (fn) { - return fn.call(this, inSender || this, inEvent); - } - }, - /** - Sends a message to myself and all of my components. - You can stop a waterfall into components owned by a - receiving object by returning a truthy value from - the event handler. - */ - waterfall: function(inMessageName, inMessage, inSender) { - //this.log(inMessageName, (inSender || this).name, "=>", this.name); - if (this.dispatchEvent(inMessageName, inMessage, inSender)) { - return true; - } - this.waterfallDown(inMessageName, inMessage, inSender || this); - }, - /** - Sends a message to all of my components, but not myself. - You can stop a waterfall into components owned by a - receiving object by returning a truthy value from - the event handler. - */ - waterfallDown: function(inMessageName, inMessage, inSender) { - for (var n in this.$) { - this.$[n].waterfall(inMessageName, inMessage, inSender); - } - } -}); - -//* @protected - -enyo.defaultCtor = enyo.Component; - -// a method to create new instances from config objects. It handles looking up the proper -// constructor based on the provided kind attribute. -enyo.create = enyo.Component.create = function(inConfig) { - if (!inConfig.kind && ("kind" in inConfig)) { - throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + (inConfig.name || "") + "]."; - } - var kind = inConfig.kind || inConfig.isa || enyo.defaultCtor; - var ctor = enyo.constructorForKind(kind); - if (!ctor) { - enyo.error('no constructor found for kind "' + kind + '"'); - ctor = enyo.Component; - } - return new ctor(inConfig); -}; - -enyo.Component.subclass = function(ctor, props) { - // Note: to reduce API surface area, sub-components are declared only as - // 'components' in both kind and instance declarations. - // - // However, 'components' from kind declarations must be handled separately - // at create-time. - // - // We rename the property here to avoid having - // to interrogate the prototype at create-time. - // - var proto = ctor.prototype; - // - if (props.components) { - proto.kindComponents = props.components; - delete proto.components; - } - // - // handlers are merged with supertype handlers - // and kind time. - // - if (props.handlers) { - var kh = proto.kindHandlers; - proto.kindHandlers = enyo.mixin(enyo.clone(kh), proto.handlers); - proto.handlers = null; - } - // events property defines published events for Component kinds - if (props.events) { - this.publishEvents(ctor, props); - } -}; - -enyo.Component.publishEvents = function(ctor, props) { - var es = props.events; - if (es) { - var cp = ctor.prototype; - for (var n in es) { - this.addEvent(n, es[n], cp); - } - } -}; - -enyo.Component.addEvent = function(inName, inValue, inProto) { - var v, fn; - if (!enyo.isString(inValue)) { - v = inValue.value; - fn = inValue.caller; - } else { - if (inName.slice(0, 2) != 'on') { - enyo.warn("enyo.Component.addEvent: event names must start with 'on'. " + inProto.kindName + - " event '" + inName + "' was auto-corrected to 'on" + inName + "'."); - inName = "on" + inName; - } - v = inValue; - fn = "do" + enyo.cap(inName.slice(2)); - } - inProto[inName] = v; - if (!inProto[fn]) { - inProto[fn] = function(inEvent) { - // bubble this event - return this.bubble(inName, inEvent); - }; - // NOTE: Mark this function as a generated event handler to allow us to - // do event chaining. Is this too complicated? - //inProto[fn]._dispatcher = true; - } -}; - -enyo.Component.prefixFromKindName = function(inKindName) { - var prefix = enyo.Component._kindPrefixi[inKindName]; - if (!prefix) { - // memoize naming information for this kind - var l = inKindName.lastIndexOf("."); - prefix = (l >= 0) ? inKindName.slice(l+1) : inKindName; - // lower-case the leading char - prefix = prefix.charAt(0).toLowerCase() + prefix.slice(1); - // memoize result - enyo.Component._kindPrefixi[inKindName] = prefix; - } - return prefix; -}; \ No newline at end of file diff --git a/enyo/source/kernel/Layout.js b/enyo/source/kernel/Layout.js deleted file mode 100644 index d666528..0000000 --- a/enyo/source/kernel/Layout.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - _enyo.Layout_ is the base kind for layout kinds. These are used by - enyo.UiComponent-based controls to allow for - arranging of the children by setting the _layoutKind_ property. - - Derived kinds will usually provide their own _layoutClass_ property to - affect the CSS rules used, and may also implement the _flow_ and _reflow_ - methods. _flow_ is called during control rendering, while _reflow_ is called - when the associated control is resized. -*/ -enyo.kind({ - name: "enyo.Layout", - kind: null, - //* CSS class that's added to the control using this layout kind - layoutClass: "", - //* @protected - constructor: function(inContainer) { - this.container = inContainer; - if (inContainer) { - inContainer.addClass(this.layoutClass); - } - }, - destroy: function() { - if (this.container) { - this.container.removeClass(this.layoutClass); - } - }, - // static property layout - flow: function() { - }, - // dynamic measuring layout - reflow: function() { - } -}); diff --git a/enyo/source/kernel/Object.js b/enyo/source/kernel/Object.js deleted file mode 100644 index 282b799..0000000 --- a/enyo/source/kernel/Object.js +++ /dev/null @@ -1,143 +0,0 @@ -/** -_enyo.Object_ implements the Enyo framework's property publishing system, as -well as providing several utility functions for its subkinds. - -Published properties are declared in a hash called _published_ within a call -to _enyo.kind_. Getter and setter methods are automatically generated for -properties declared in this manner. Also, by convention, the setter for a -published property will trigger an optional _<propertyName>Changed_ method -when called. - -For more information, see the [documentation on Published -Properties](https://github.com/enyojs/enyo/wiki/Published-Properties) in the -Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Object", - //* @protected - // has no base kind - kind: null, - constructor: function() { - enyo._objectCount++; - }, - /** - Sets property named 'n' with value 'v' and then invokes callback - function 'cf' (if specified), passing in the original value of 'n'. - All property setting should bottleneck here so that objects can - observe changes wlog. - */ - setPropertyValue: function(n, v, cf) { - if (this[cf]) { - var old = this[n]; - this[n] = v; - this[cf](old); - } else { - this[n] = v; - } - }, - _setProperty: function(n, v, cf) { - this.setPropertyValue(n, v, (this.getProperty(n) !== v) && cf); - }, - //* @public - //* Destroys object with passed-in name. - destroyObject: function(inName) { - if (this[inName] && this[inName].destroy) { - this[inName].destroy(); - } - this[inName] = null; - }, - //* Gets value of property with passed-in name. - getProperty: function(n) { - var getter = "get" + enyo.cap(n); - if (this[getter]) { - return this[getter](); - } - return this[n]; - }, - //* Sets value of property named 'n' to 'v'. - setProperty: function(n, v) { - var setter = "set" + enyo.cap(n); - if (this[setter]) { - this[setter](v); - } else { - this._setProperty(n, v, n + "Changed"); - } - }, - /** - Sends a log message to the console, prepended with the name of the kind - and method from which _log_ was invoked. Multiple arguments are coerced - to String and joined with spaces. - - enyo.kind({ - name: "MyObject", - kind: enyo.Object, - hello: function() { - this.log("says", "hi"); - // shows in the console: MyObject.hello: says hi - } - }); - */ - log: function() { - var acc = arguments.callee.caller; - var nom = ((acc ? acc.nom : "") || "(instance method)") + ":"; - enyo.logging.log("log", [nom].concat(enyo.cloneArray(arguments))); - }, - //* Same as _log_, except uses the console's warn method (if it exists). - warn: function() { - this._log("warn", arguments); - }, - //* Same as _log_, except uses the console's error method (if it exists). - error: function() { - this._log("error", arguments); - }, - //* @protected - _log: function(inMethod, inArgs) { - if (enyo.logging.shouldLog(inMethod)) { - try { - throw new Error(); - } catch(x) { - enyo.logging._log(inMethod, [inArgs.callee.caller.nom + ": "].concat(enyo.cloneArray(inArgs))); - enyo.log(x.stack); - } - } - } -}); - -//* @protected - -enyo._objectCount = 0; - -enyo.Object.subclass = function(ctor, props) { - this.publish(ctor, props); -}; - -enyo.Object.publish = function(ctor, props) { - var pp = props.published; - if (pp) { - var cp = ctor.prototype; - for (var n in pp) { - enyo.Object.addGetterSetter(n, pp[n], cp); - } - } -}; - -enyo.Object.addGetterSetter = function(inName, inValue, inProto) { - var priv_n = inName; - inProto[priv_n] = inValue; - // - var cap_n = enyo.cap(priv_n); - var get_n = "get" + cap_n; - if (!inProto[get_n]) { - inProto[get_n] = function() { - return this[priv_n]; - }; - } - // - var set_n = "set" + cap_n; - var change_n = priv_n + "Changed"; - if (!inProto[set_n]) { - inProto[set_n] = function(v) { - this._setProperty(priv_n, v, change_n); - }; - } -}; diff --git a/enyo/source/kernel/Oop.js b/enyo/source/kernel/Oop.js deleted file mode 100644 index 7e588c4..0000000 --- a/enyo/source/kernel/Oop.js +++ /dev/null @@ -1,218 +0,0 @@ -//* @public -/** - Creates a JavaScript constructor function with a prototype defined by - _inProps_. - - _enyo.kind_ makes it easy to build a constructor-with-prototype (like a - class) that has advanced features like prototype-chaining (inheritance). - - A plug-in system is included for extending the abilities of the kind - generator, and constructors are allowed to perform custom operations when - subclassed. - - If you make changes to _enyo.kind_, be sure to add or update the appropriate - [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests). - - For more information, see the documentation on - [Creating Kinds](https://github.com/enyojs/enyo/wiki/Creating-Kinds) - in the Enyo Developer Guide. -*/ -enyo.kind = function(inProps) { - // kind-name to constructor map could be faulty now that a new kind exists, so we simply destroy the memoizations - enyo._kindCtors = {}; - // extract 'name' property - var name = inProps.name || ""; - delete inProps.name; - // extract 'kind' property - var hasKind = ("kind" in inProps); - var kind = inProps.kind; - delete inProps.kind; - // establish base class reference - var base = enyo.constructorForKind(kind); - var isa = base && base.prototype || null; - // if we have an explicit kind property with value undefined, we probably - // tried to reference a kind that is not yet in scope - if (hasKind && kind === undefined || base === undefined) { - var problem = kind === undefined ? 'undefined kind' : 'unknown kind (' + kind + ')'; - throw "enyo.kind: Attempt to subclass an " + problem + ". Check dependencies for [" + (name || "") + "]."; - } - // make a boilerplate constructor - var ctor = enyo.kind.makeCtor(); - // semi-reserved word 'constructor' causes problems with Prototype and IE, so we rename it here - if (inProps.hasOwnProperty("constructor")) { - inProps._constructor = inProps.constructor; - delete inProps.constructor; - } - // create our prototype - //ctor.prototype = isa ? enyo.delegate(isa) : {}; - enyo.setPrototype(ctor, isa ? enyo.delegate(isa) : {}); - // put in our props - enyo.mixin(ctor.prototype, inProps); - // alias class name as 'kind' in the prototype - ctor.prototype.kindName = name; - // cache superclass constructor - ctor.prototype.base = base; - // reference our real constructor - ctor.prototype.ctor = ctor; - // support pluggable 'features' - enyo.forEach(enyo.kind.features, function(fn){ fn(ctor, inProps); }); - // put reference into namespace - enyo.setObject(name, ctor); - return ctor; -}; - -/** - Creates a Singleton - - enyo.singleton({ - kind: Control, - name: "app.MySingleton", - published: { - value: "foo" - }, - makeSomething: function() { - //... - } - }); - - app.MySingleton.makeSomething(); - app.MySingleton.setValue("bar"); -*/ -enyo.singleton = function(conf, context) { - // extract 'name' property (the name of our singleton) - var name = conf.name; - delete(conf.name); - // create an unnamed kind and save its constructor's function - var kind = enyo.kind(conf); - // create the singleton with the previous name and constructor - enyo.setObject(name, new kind(), context); -}; - -//* @protected -enyo.kind.makeCtor = function() { - return function() { - if (!(this instanceof arguments.callee)) { - throw "enyo.kind: constructor called directly, not using 'new'"; - } - - // two-pass instantiation - var result; - if (this._constructor) { - // pure construction - result = this._constructor.apply(this, arguments); - } - // defer initialization until entire constructor chain has finished - if (this.constructed) { - // post-constructor initialization - this.constructed.apply(this, arguments); - } - if (result) { - return result; - } - }; -}; - -// classes referenced by name can omit this namespace (e.g. "Button" instead of "enyo.Button") -enyo.kind.defaultNamespace = "enyo"; - -// -// feature hooks for the oop system -// -enyo.kind.features = []; - -// -// 'inherited' feature -// -enyo.kind.features.push(function(ctor, props) { - var proto = ctor.prototype; - if (!proto.inherited) { - proto.inherited = enyo.kind.inherited; - } - if (proto.base) { - // decorate function properties to support inherited (do this ex post facto so that - // ctor.prototype is known, relies on elements in props being copied by reference) - for (var n in props) { - var p = props[n]; - if (enyo.isFunction(p)) { - p._inherited = proto.base.prototype[n] || enyo.nop; - // FIXME: we used to need some extra values for inherited, then inherited got cleaner - // but in the meantime we used these values to support logging in Object. - // For now we support this legacy situation, by suppling logging information here. - p.nom = proto.kindName + '.' + n + '()'; - } - } - } -}); - -enyo.kind.inherited = function(args, newArgs) { - return args.callee._inherited.apply(this, newArgs || args); -}; - -// -// 'statics' feature -// -enyo.kind.features.push(function(ctor, props) { - // install common statics - enyo.mixin(ctor, enyo.kind.statics); - // move props statics to constructor - if (props.statics) { - enyo.mixin(ctor, props.statics); - delete ctor.prototype.statics; - } - // allow superclass customization - var base = ctor.prototype.base; - while (base) { - base.subclass(ctor, props); - base = base.prototype.base; - } -}); - -enyo.kind.statics = { - subclass: function(ctor, props) { - //enyo.log("subclassing [" + ctor.prototype.kind + "] from [", this.prototype.kind + "]"); - }, - extend: function(props) { - enyo.mixin(this.prototype, props); - // support pluggable 'features' - var ctor = this; - enyo.forEach(enyo.kind.features, function(fn){ fn(ctor, props); }); - } -}; - -// -// factory for kinds identified by strings -// -enyo._kindCtors = {}; - -enyo.constructorForKind = function(inKind) { - if (inKind === null || enyo.isFunction(inKind)) { - // in inKind is a function or explicitly null, then that's ctor, full stop. - return inKind; - } - if (inKind) { - // use memoized constructor if available... - var ctor = enyo._kindCtors[inKind]; - if (ctor) { - return ctor; - } - // otherwise look it up and memoize what we find - // - // if inKind is an object in enyo, say "Control", then ctor = enyo["Control"] - // if inKind is a path under enyo, say "Heritage.Button", then ctor = enyo["Heritage.Button"] || enyo.Heritage.Button - // if inKind is a fully qualified path, say "enyo.Heritage.Button", then ctor = enyo["enyo.Heritage.Button"] || enyo.enyo.Heritage.Button || enyo.Heritage.Button - // - // Note that kind "Foo" will resolve to enyo.Foo before resolving to global "Foo". - // This is important so "Image" will map to built-in Image object, instead of enyo.Image control. - return enyo._kindCtors[inKind] = enyo.Theme[inKind] || enyo[inKind] || enyo.getObject(inKind, false, enyo) || window[inKind] || enyo.getObject(inKind); - } - return enyo.defaultCtor; -}; - -// -// namespace for current theme ("enyo.Theme.Button" references the Button specialization for the current theme) -// -enyo.Theme = {}; - -enyo.registerTheme = function(inNamespace) { - enyo.mixin(enyo.Theme, inNamespace); -}; \ No newline at end of file diff --git a/enyo/source/kernel/Signals.js b/enyo/source/kernel/Signals.js deleted file mode 100644 index c3d7500..0000000 --- a/enyo/source/kernel/Signals.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - _enyo.Signals_ components are used to listen to global messages. - - An object with a Signals component can listen to messages sent from anywhere - by declaring handlers for them. - - DOM events that have no node targets are broadcast as signals. These events - include Window events, like _onload_ and _onbeforeunload_, and events that - occur directly on _document_, like _onkeypress_ if _document_ has the focus. - - For more information, see the - Signals documentation - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Signals", - kind: enyo.Component, - //* @protected - create: function() { - this.inherited(arguments); - enyo.Signals.addListener(this); - }, - destroy: function() { - enyo.Signals.removeListener(this); - this.inherited(arguments); - }, - notify: function(inMsg, inPayload) { - this.dispatchEvent(inMsg, inPayload); - }, - statics: { - listeners: [], - addListener: function(inListener) { - this.listeners.push(inListener); - }, - removeListener: function(inListener) { - enyo.remove(inListener, this.listeners); - }, - send: function(inMsg, inPayload) { - enyo.forEach(this.listeners, function(l) { - l.notify(inMsg, inPayload); - }); - } - } -}); diff --git a/enyo/source/kernel/UiComponent.js b/enyo/source/kernel/UiComponent.js deleted file mode 100644 index c3f0141..0000000 --- a/enyo/source/kernel/UiComponent.js +++ /dev/null @@ -1,316 +0,0 @@ -/** - _enyo.UiComponent_ implements a container strategy suitable for presentation - layers. - - UiComponent itself is abstract. Concrete subkinds include - enyo.Control (for HTML/DOM) and - enyo.canvas.Control - (for Canvas contexts). -*/ -enyo.kind({ - name: "enyo.UiComponent", - kind: enyo.Component, - published: { - //* The UiComponent that physically contains this component in the DOM - container: null, - /** - The UiComponent that owns this component for purposes of event - propagation - */ - parent: null, - /** - The UiComponent that will physically contain new items added by - calls to _createComponent_ - */ - controlParentName: "client", - //* A kind used to manage the size and placement of child components - layoutKind: "" - }, - handlers: { - onresize: "resizeHandler" - }, - /** - When set, provides a control reference used to indicate where a - newly-created component should be added in the UiComponent's array of - children. This is typically used when dynamically creating children - (rather than at design time). If set to null, the new control will be - added at the beginning of the array; if set to a specific existing - control, the new control will be added before the specified control. If - left undefined, the default behavior is to add the new control at the - end of the array. - */ - addBefore: undefined, - //* @protected - statics: { - _resizeFlags: {showingOnly: true} // don't waterfall these events into hidden controls - }, - create: function() { - this.controls = []; - this.children = []; - this.containerChanged(); - this.inherited(arguments); - this.layoutKindChanged(); - }, - destroy: function() { - // Destroys all non-chrome controls (regardless of owner). - this.destroyClientControls(); - // Removes us from our container. - this.setContainer(null); - // Destroys chrome controls owned by this. - this.inherited(arguments); - }, - importProps: function(inProps) { - this.inherited(arguments); - if (!this.owner) { - //this.log("registering ownerless control [" + this.kindName + "] with enyo.master"); - this.owner = enyo.master; - } - }, - // As implemented, _controlParentName_ only works to identify an owned - // control created via _createComponents_ (i.e., usually in our _components_ - // block). To attach a _controlParent_ via other means, one must call - // _discoverControlParent_ or set _controlParent_ directly. - // - // We could call _discoverControlParent_ in _addComponent_, but it would - // cause a lot of useless checking. - createComponents: function() { - var results = this.inherited(arguments); - this.discoverControlParent(); - return results; - }, - discoverControlParent: function() { - this.controlParent = this.$[this.controlParentName] || this.controlParent; - }, - adjustComponentProps: function(inProps) { - // Components we create have us as a container by default. - inProps.container = inProps.container || this; - this.inherited(arguments); - }, - // containment - containerChanged: function(inOldContainer) { - if (inOldContainer) { - inOldContainer.removeControl(this); - } - if (this.container) { - this.container.addControl(this, this.addBefore); - } - }, - // parentage - parentChanged: function(inOldParent) { - if (inOldParent && inOldParent != this.parent) { - inOldParent.removeChild(this); - } - }, - //* @public - // Note: Oddly, a Control is considered a descendant of itself. - isDescendantOf: function(inAncestor) { - var p = this; - while (p && p!=inAncestor) { - p = p.parent; - } - return inAncestor && (p == inAncestor); - }, - /** - Returns all controls. - */ - getControls: function() { - return this.controls; - }, - /** - Returns all non-chrome controls. - */ - getClientControls: function() { - var results = []; - for (var i=0, cs=this.controls, c; (c=cs[i]); i++) { - if (!c.isChrome) { - results.push(c); - } - } - return results; - }, - /** - Destroys "client controls", the same set of controls returned by - _getClientControls_. - */ - destroyClientControls: function() { - var c$ = this.getClientControls(); - for (var i=0, c; (c=c$[i]); i++) { - c.destroy(); - } - }, - //* @protected - addControl: function(inControl, inBefore) { - // Called to add an already created control to the object's control list. It is - // not used to create controls and should likely not be called directly. - // It can be overridden to detect when controls are added. - this.controls.push(inControl); - // When we add a Control, we also establish a parent. - this.addChild(inControl, inBefore); - }, - removeControl: function(inControl) { - // Called to remove a control from the object's control list. As with addControl it - // can be overridden to detect when controls are removed. - // When we remove a Control, we also remove it from its parent. - inControl.setParent(null); - return enyo.remove(inControl, this.controls); - }, - indexOfControl: function(inControl) { - return enyo.indexOf(inControl, this.controls); - }, - indexOfClientControl: function(inControl) { - return enyo.indexOf(inControl, this.getClientControls()); - }, - indexInContainer: function() { - return this.container.indexOfControl(this); - }, - clientIndexInContainer: function() { - return this.container.indexOfClientControl(this); - }, - controlAtIndex: function(inIndex) { - return this.controls[inIndex]; - }, - // children - addChild: function(inChild, inBefore) { - // if inBefore is undefined, add to the end of the child list. - // If it's null, add to front of list, otherwise add before the - // specified control. - // - // allow delegating the child to a different container - if (this.controlParent /*&& !inChild.isChrome*/) { - // this.controlParent might have a controlParent, and so on; seek the ultimate parent - // inBefore is not passed because that control won't be in the controlParent's scope - this.controlParent.addChild(inChild); - } else { - // NOTE: addChild drives setParent. - // It's the opposite for setContainer, where containerChanged (in Containable) - // drives addControl. - // Because of the way 'parent' is derived from 'container', this difference is - // helpful for implementing controlParent. - // By the same token, since 'parent' is derived from 'container', setParent is - // not intended to be called by client code. Therefore, the lack of parallelism - // should be private to this implementation. - // Set the child's parent property to this - inChild.setParent(this); - // track in children array - if (inBefore !== undefined) { - var idx = (inBefore === null) ? 0 : this.indexOfChild(inBefore); - this.children.splice(idx, 0, inChild); - } else { - this.children.push(inChild); - } - } - }, - removeChild: function(inChild) { - return enyo.remove(inChild, this.children); - }, - indexOfChild: function(inChild) { - return enyo.indexOf(inChild, this.children); - }, - layoutKindChanged: function() { - if (this.layout) { - this.layout.destroy(); - } - this.layout = enyo.createFromKind(this.layoutKind, this); - if (this.generated) { - this.render(); - } - }, - flow: function() { - if (this.layout) { - this.layout.flow(); - } - }, - // CAVEAT: currently we use the entry point for both - // post-render layout work *and* post-resize layout work. - reflow: function() { - if (this.layout) { - this.layout.reflow(); - } - }, - /** - Call after this control has been resized to allow it to process the size change. - To respond to a resize, override _resizeHandler_ instead. - */ - // syntactic sugar for 'waterfall("onresize")' - resized: function() { - this.waterfall("onresize", enyo.UiComponent._resizeFlags); - this.waterfall("onpostresize", enyo.UiComponent._resizeFlags); - }, - //* @protected - resizeHandler: function() { - // FIXME: once we are in the business of reflowing layouts on resize, then we have an - // inside/outside problem: some scenarios will need to reflow before child - // controls reflow, and some will need to reflow after. Even more complex scenarios - // have circular dependencies, and can require multiple passes or other resolution. - // When we can rely on CSS to manage reflows we do not have these problems. - this.reflow(); - }, - /** - Sends a message to all my descendents. - */ - waterfallDown: function(inMessage, inPayload, inSender) { - // Note: Controls will generally be both in a $ hash and a child list somewhere. - // Attempt to avoid duplicated messages by sending only to components that are not - // UiComponent, as those components are guaranteed not to be in a child list. - // May cause a problem if there is a scenario where a UiComponent owns a pure - // Component that in turn owns Controls. - // - // waterfall to all pure components - for (var n in this.$) { - if (!(this.$[n] instanceof enyo.UiComponent)) { - this.$[n].waterfall(inMessage, inPayload, inSender); - } - } - // waterfall to my children - for (var i=0, cs=this.children, c; (c=cs[i]); i++) { - // Do not send {showingOnly: true} events to hidden controls. This flag is set for resize events - // which are broadcast from within the framework. This saves a *lot* of unnecessary layout. - // TODO: Maybe remember that we did this, and re-send those messages on setShowing(true)? - // No obvious problems with it as-is, though - if (c.showing || !(inPayload && inPayload.showingOnly)) { - c.waterfall(inMessage, inPayload, inSender); - } - } - }, - getBubbleTarget: function() { - return this.parent; - } -}); - -enyo.createFromKind = function(inKind, inParam) { - var ctor = inKind && enyo.constructorForKind(inKind); - if (ctor) { - return new ctor(inParam); - } -}; - -// -// Default owner for ownerless UiComponents to allow notifying such UiComponents -// of important system events like window resize. -// -// NOTE: Ownerless UiComponents will not be garbage collected unless explicitly -// destroyed, as they will be referenced by _enyo.master_. -// -enyo.master = new enyo.Component({ - name: "master", - notInstanceOwner: true, - eventFlags: {showingOnly: true}, // don't waterfall these events into hidden controls - getId: function() { - return ''; - }, - isDescendantOf: enyo.nop, - bubble: function(inEventName, inEvent, inSender) { - //enyo.log("master event: " + inEventName); - if (inEventName == "onresize") { - // Resize is special; waterfall this message. - // This works because master is a Component, so it waterfalls - // to its owned Components (i.e., master has no children). - enyo.master.waterfallDown("onresize", this.eventFlags); - enyo.master.waterfallDown("onpostresize", this.eventFlags); - } else { - // All other top-level events are sent only to interested Signal - // receivers. - enyo.Signals.send(inEventName, inEvent); - } - } -}); diff --git a/enyo/source/kernel/job.js b/enyo/source/kernel/job.js deleted file mode 100644 index c50b72e..0000000 --- a/enyo/source/kernel/job.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - Invokes function _inJob_ after _inWait_ milliseconds have elapsed since the - last time _inJobName_ was referenced. - - Jobs can be used to throttle behaviors. If some event may occur once or - multiple times, but we want a response to occur only once every _n_ seconds, - we can use a job. - - onscroll: function() { - // updateThumb will be called, but only when 1s has elapsed since the - // last onscroll - enyo.job("updateThumb", enyo.bind(this, "updateThumb"), 1000); - } -*/ -enyo.job = function(inJobName, inJob, inWait) { - enyo.job.stop(inJobName); - enyo.job._jobs[inJobName] = setTimeout(function() { - enyo.job.stop(inJobName); - inJob(); - }, inWait); -}; - -/** - Cancels the named job, if it has not already fired. -*/ -enyo.job.stop = function(inJobName) { - if (enyo.job._jobs[inJobName]) { - clearTimeout(enyo.job._jobs[inJobName]); - delete enyo.job._jobs[inJobName]; - } -}; - -enyo.job._jobs = {}; \ No newline at end of file diff --git a/enyo/source/kernel/lang.js b/enyo/source/kernel/lang.js deleted file mode 100644 index bb4cd5c..0000000 --- a/enyo/source/kernel/lang.js +++ /dev/null @@ -1,416 +0,0 @@ -(function(){ - //* @protected - enyo.global = this; - - enyo._getProp = function(parts, create, context) { - var obj = context || enyo.global; - for(var i=0, p; obj && (p=parts[i]); i++){ - obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined)); - } - return obj; - }; - - //* @public - - /** - Sets object _name_ to _value_. _name_ may use dot notation, and - intermediate objects are created as necessary. - - // set foo.bar.baz to 3; if foo or foo.bar do not exist, they are created - enyo.setObject("foo.bar.baz", 3); - - Optionally, _name_ may be relative to object _context_. - - // create foo.zot and set foo.zot.zap to null - enyo.setObject("zot.zap", null, foo); - */ - enyo.setObject = function(name, value, context) { - var parts=name.split("."), p=parts.pop(), obj=enyo._getProp(parts, true, context); - return obj && p ? (obj[p]=value) : undefined; - }; - - /** - Gets object _name_. _name_ may use dot notation. Intermediate objects - are created if the _create_ argument is truthy. - - // get the value of foo.bar, or undefined if foo doesn't exist - var value = enyo.getObject("foo.bar"); - - // get the value of foo.bar; if foo.bar doesn't exist, - // it's assigned an empty object, which is then returned - var value = enyo.getObject("foo.bar", true); - - Optionally, _name_ may be relative to object _context_. - - // get the value of foo.zot.zap, or undefined if foo.zot doesn't exist - var value = enyo.getObject("zot.zap", false, foo); - */ - enyo.getObject = function(name, create, context) { - return enyo._getProp(name.split("."), create, context); - }; - - /** - Returns a random Integer between 0 and _inBound_ (0 <= random integer < _inBound_). - - var randomLetter = String.fromCharCode(enyo.irand(26) + 97); - */ - enyo.irand = function(inBound) { - return Math.floor(Math.random() * inBound); - }; - - //* Returns _inString_ with the first letter capitalized. - enyo.cap = function(inString) { - return inString.slice(0, 1).toUpperCase() + inString.slice(1); - }; - - //* Returns _inString_ with the first letter un-capitalized. - enyo.uncap = function(inString) { - return inString.slice(0, 1).toLowerCase() + inString.slice(1); - }; - - enyo.format = function(inVarArgs) { - var pattern = /\%./g; - var arg = 0, template = inVarArgs, args = arguments; - var replacer = function(inCode) { - return args[++arg]; - }; - return template.replace(pattern, replacer); - }; - - var toString = Object.prototype.toString; - - //* Returns true if _it_ is a string. - enyo.isString = function(it) { - return toString.call(it) === "[object String]"; - }; - - //* Returns true if _it_ is a function. - enyo.isFunction = function(it) { - return toString.call(it) === "[object Function]"; - }; - - //* Returns true if _it_ is an array. - enyo.isArray = Array.isArray || function(it) { - return toString.call(it) === "[object Array]"; - }; - - //* Returns true if the argument is true - enyo.isTrue = function(it) { - return !(it === "false" || it === false || it === 0 || it === null || it === undefined); - }; - - //* Returns the index of the element in _inArray_ that is equivalent (==) to _inElement_, or -1 if no element is found. - enyo.indexOf = function(inElement, inArray, fromIndex) { - if (inArray.indexOf) { - return inArray.indexOf(inElement, fromIndex); - } - - if (fromIndex) { - if (fromIndex < 0) { - fromIndex = 0; - } - - if (fromIndex > inArray.length) { - return -1; - } - } - - for (var i=fromIndex || 0, l=inArray.length, e; (e=inArray[i]) || (i= 0) { - inArray.splice(i, 1); - } - }; - - /** - Invokes _inFunc_ on each element of _inArray_. - If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. - */ - enyo.forEach = function(inArray, inFunc, inContext) { - if (inArray) { - var c = inContext || this; - if (enyo.isArray(inArray) && inArray.forEach) { - inArray.forEach(inFunc, c); - } else { - var a = Object(inArray); - var al = a.length >>> 0; - for (var i = 0; i < al; i++) { - if (i in a) { - inFunc.call(c, a[i], i, a); - } - } - } - } - }; - - /** - Invokes _inFunc_ on each element of _inArray_, and returns the results as an Array. - If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. - */ - enyo.map = function(inArray, inFunc, inContext) { - var c = inContext || this; - if (enyo.isArray(inArray) && inArray.map) { - return inArray.map(inFunc, c); - } else { - var results = []; - var add = function(e, i, a) { - results.push(inFunc.call(c, e, i, a)); - }; - enyo.forEach(inArray, add, c); - return results; - } - }; - - /** - Creates a new array with all elements of _inArray_ that pass the test implemented by _inFunc_. - If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. - */ - enyo.filter = function(inArray, inFunc, inContext) { - var c = inContext || this; - if (enyo.isArray(inArray) && inArray.filter) { - return inArray.filter(inFunc, c); - } else { - var results = []; - var f = function(e, i, a) { - var eo = e; - if (inFunc.call(c, e, i, a)) { - results.push(eo); - } - }; - enyo.forEach(inArray, f, c); - return results; - } - }; - - /** - Returns an array of all own enumerable properties found on _inObject_. - */ - enyo.keys = Object.keys || function(inObject) { - var results = []; - var hop = Object.prototype.hasOwnProperty; - for (var prop in inObject) { - if (hop.call(inObject, prop)) { - results.push(prop); - } - } - // *sigh* IE 8 - if (!({toString: null}).propertyIsEnumerable("toString")) { - var dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ]; - for (var i = 0, p; (p = dontEnums[i]); i++) { - if (hop.call(inObject, p)) { - results.push(p); - } - } - } - return results; - }; - - /** - Clones an existing Array, or converts an array-like object into an Array. - - If _inOffset_ is non-zero, the cloning is started from that index in the source Array. - The clone may be appended to an existing Array by passing the existing Array as _inStartWith_. - - Array-like objects have _length_ properties, and support square-bracket notation ([]). - Often array-like objects do not support Array methods, such as _push_ or _concat_, and - must be converted to Arrays before use. - - The special _arguments_ variable is an example of an array-like object. - */ - enyo.cloneArray = function(inArrayLike, inOffset, inStartWith) { - var arr = inStartWith || []; - for(var i = inOffset || 0, l = inArrayLike.length; ienyo.log will output - if the level is 20 or above, enyo.warn at 10, and - enyo.error at 0. -*/ -enyo.setLogLevel = function(inLevel) { - var ll = parseInt(inLevel, 0); - if (isFinite(ll)) { - enyo.logging.level = ll; - } -}; - -/** - Sends a log message to the console, if the current log level allows for it. - - Objects are converted to JSON automatically. - - Multiple arguments are coerced to String and joined with spaces. -*/ -enyo.log = function() { - enyo.logging.log("log", arguments); -}; - -//* Same as _log_, except uses the console's warn method (if it exists). -enyo.warn = function() { - enyo.logging.log("warn", arguments); -}; - -//* Same as _log_, except uses the console's error method (if it exists). -enyo.error = function() { - enyo.logging.log("error", arguments); -}; \ No newline at end of file diff --git a/enyo/source/kernel/macroize.js b/enyo/source/kernel/macroize.js deleted file mode 100644 index 489499b..0000000 --- a/enyo/source/kernel/macroize.js +++ /dev/null @@ -1,74 +0,0 @@ -//* @public - -/** - Populates a string template with data values. - - Returns a copy of _inText_, with macros defined by _inPattern_ replaced by - named values in _inMap_. - - _inPattern_ may be omitted, in which case the default macro pattern is used. - The default pattern matches macros of the form - - {$name} - - Example: - - // Returns "My name is Barney." - enyo.macroize("My name is {$name}.", {name: "Barney"}); - - Dot notation is supported, like so: - - var info = { - product_0: { - name: "Gizmo" - weight: 3 - } - } - // Returns "Each Gizmo weighs 3 pounds." - enyo.macroize("Each {$product_0.name} weighs {$product_0.weight} pounds.", info); -*/ -enyo.macroize = function(inText, inMap, inPattern) { - var v, working, result = inText, pattern = inPattern || enyo.macroize.pattern; - var fn = function(macro, name) { - v = enyo.getObject(name, false, inMap); - if (v === undefined || v === null) { - return "{$" + name + "}"; - } - working = true; - return v; - }; - var prevent = 0; - do { - working = false; - result = result.replace(pattern, fn); - // if iterating more than 20 times, we assume a recursion (we should probably throw) - if (++prevent >= 20) { - throw("enyo.macroize: recursion too deep"); - } - } while (working); - return result; -}; - -/** - Similar to _enyo.macroize_, but performs only one iteration of the _replace_ - call. This means that recursive expansion of macros isn't possible, but it - avoids the extra processing needed to find recursive use. -*/ -enyo.quickMacroize = function(inText, inMap, inPattern) { - var v, working, result = inText, pattern = inPattern || enyo.macroize.pattern; - var fn = function(macro, name) { - if (name in inMap) { - v = inMap[name]; - } else { - v = enyo.getObject(name, false, inMap); - } - return (v === undefined || v === null) ? "{$" + name + "}" : v; - }; - result = result.replace(pattern, fn); - return result; -}; - -//* @protected - -// Matches macros of the form {$name}. -enyo.macroize.pattern = /\{\$([^{}]*)\}/g; diff --git a/enyo/source/kernel/package.js b/enyo/source/kernel/package.js deleted file mode 100644 index 0011420..0000000 --- a/enyo/source/kernel/package.js +++ /dev/null @@ -1,12 +0,0 @@ -enyo.depends( - "log.js", - "lang.js", - "job.js", - "macroize.js", - "Oop.js", - "Object.js", - "Component.js", - "UiComponent.js", - "Layout.js", - "Signals.js" -); diff --git a/enyo/source/package.js b/enyo/source/package.js deleted file mode 100644 index ceffe7c..0000000 --- a/enyo/source/package.js +++ /dev/null @@ -1,7 +0,0 @@ -enyo.depends( - "kernel", - "ajax", - "dom", - "touch", - "ui" -); diff --git a/enyo/source/touch/ScrollMath.js b/enyo/source/touch/ScrollMath.js deleted file mode 100644 index 8fb592d..0000000 --- a/enyo/source/touch/ScrollMath.js +++ /dev/null @@ -1,305 +0,0 @@ -/** -_enyo.ScrollMath_ implements a scrolling dynamics simulation. It is a helper -kind used by other scroller kinds, such as -enyo.TouchScrollStrategy. - -_enyo.ScrollMath_ is not typically created in application code. -*/ -enyo.kind({ - name: "enyo.ScrollMath", - kind: enyo.Component, - published: { - //* True if vertical scrolling is enabled - vertical: true, - //* True if horizontal scrolling is enabled - horizontal: true - }, - events: { - //* Fires when scroll action starts. - onScrollStart: "", - //* Fires while scroll action is in progress. - onScroll: "", - //* Fires when scroll action stops. - onScrollStop: "" - }, - //* 'Spring' damping returns the scroll position to a value inside the - //* boundaries. Lower values provide _faster_ snapback. - kSpringDamping: 0.93, - //* 'Drag' damping resists dragging the scroll position beyond the - //* boundaries. Lower values provide _more_ resistance. - kDragDamping: 0.5, - //* 'Friction' damping reduces momentum over time. Lower values provide - //* _more_ friction. - kFrictionDamping: 0.97, - //* Additional 'friction' damping applied when momentum carries the viewport - //* into overscroll. Lower values provide _more_ friction. - kSnapFriction: 0.9, - //* Scalar applied to 'flick' event velocity - kFlickScalar: 15, - //* Limits the maximum allowable flick. On Android > 2, we limit this to - //* prevent compositing artifacts. - kMaxFlick: enyo.platform.android > 2 ? 2 : 1e9, - //* The value used in friction() to determine if the delta (e.g., y - y0) is - //* close enough to zero to consider as zero - kFrictionEpsilon: 1e-2, - //* Top snap boundary, generally 0 - topBoundary: 0, - //* Right snap boundary, generally (viewport width - content width) - rightBoundary: 0, - //* Bottom snap boundary, generally (viewport height - content height) - bottomBoundary: 0, - //* Left snap boundary, generally 0 - leftBoundary: 0, - //* Animation time step - interval: 20, - //* Flag to enable frame-based animation; if false, time-based animation is used - fixedTime: true, - //* @protected - // simulation state - x0: 0, - x: 0, - y0: 0, - y: 0, - destroy: function() { - this.stop(); - this.inherited(arguments); - }, - /** - Simple Verlet integrator for simulating Newtonian motion. - */ - verlet: function(p) { - var x = this.x; - this.x += x - this.x0; - this.x0 = x; - // - var y = this.y; - this.y += y - this.y0; - this.y0 = y; - }, - /** - Boundary damping function. - Returns damped 'value' based on 'coeff' on one side of 'origin'. - */ - damping: function(value, origin, coeff, sign) { - var kEpsilon = 0.5; - // - // this is basically just value *= coeff (generally, coeff < 1) - // - // 'sign' and the conditional is to force the damping to only occur - // on one side of the origin. - // - var dv = value - origin; - // Force close-to-zero to zero - if (Math.abs(dv) < kEpsilon) { - return origin; - } - return value*sign > origin*sign ? coeff * dv + origin : value; - }, - /** - Dual-boundary damping function. - Returns damped 'value' based on 'coeff' when exceeding either boundary. - */ - boundaryDamping: function(value, aBoundary, bBoundary, coeff) { - return this.damping(this.damping(value, aBoundary, coeff, 1), bBoundary, coeff, -1); - }, - /** - Simulation constraints (spring damping occurs here) - */ - constrain: function() { - var y = this.boundaryDamping(this.y, this.topBoundary, this.bottomBoundary, this.kSpringDamping); - if (y != this.y) { - // ensure snapping introduces no velocity, add additional friction - this.y0 = y - (this.y - this.y0) * this.kSnapFriction; - this.y = y; - } - var x = this.boundaryDamping(this.x, this.leftBoundary, this.rightBoundary, this.kSpringDamping); - if (x != this.x) { - this.x0 = x - (this.x - this.x0) * this.kSnapFriction; - this.x = x; - } - }, - /** - The friction function - */ - friction: function(inEx, inEx0, inCoeff) { - // implicit velocity - var dp = this[inEx] - this[inEx0]; - // let close-to-zero collapse to zero (i.e. smaller than epsilon is considered zero) - var c = Math.abs(dp) > this.kFrictionEpsilon ? inCoeff : 0; - // reposition using damped velocity - this[inEx] = this[inEx0] + c * dp; - }, - // one unit of time for simulation - frame: 10, - // piece-wise constraint simulation - simulate: function(t) { - while (t >= this.frame) { - t -= this.frame; - if (!this.dragging) { - this.constrain(); - } - this.verlet(); - this.friction('y', 'y0', this.kFrictionDamping); - this.friction('x', 'x0', this.kFrictionDamping); - } - return t; - }, - animate: function() { - this.stop(); - // time tracking - var t0 = enyo.now(), t = 0; - // delta tracking - var x0, y0; - // animation handler - var fn = enyo.bind(this, function() { - // wall-clock time - var t1 = enyo.now(); - // schedule next frame - this.job = enyo.requestAnimationFrame(fn); - // delta from last wall clock time - var dt = t1 - t0; - // record the time for next delta - t0 = t1; - // user drags override animation - if (this.dragging) { - this.y0 = this.y = this.uy; - this.x0 = this.x = this.ux; - } - // frame-time accumulator - // min acceptable time is 16ms (60fps) - t += Math.max(16, dt); - // alternate fixed-time step strategy: - if (this.fixedTime && !this.isInOverScroll()) { - t = this.interval; - } - // consume some t in simulation - t = this.simulate(t); - // scroll if we have moved, otherwise the animation is stalled and we can stop - if (y0 != this.y || x0 != this.x) { - //this.log(this.y, y0); - this.scroll(); - } else if (!this.dragging) { - this.stop(true); - this.scroll(); - } - y0 = this.y; - x0 = this.x; - }); - this.job = enyo.requestAnimationFrame(fn); - }, - //* @protected - start: function() { - if (!this.job) { - this.animate(); - this.doScrollStart(); - } - }, - stop: function(inFireEvent) { - this.job = enyo.cancelRequestAnimationFrame(this.job); - if (inFireEvent) { - this.doScrollStop(); - } - }, - stabilize: function() { - this.start(); - var y = Math.min(this.topBoundary, Math.max(this.bottomBoundary, this.y)); - var x = Math.min(this.leftBoundary, Math.max(this.rightBoundary, this.x)); - this.y = this.y0 = y; - this.x = this.x0 = x; - this.scroll(); - this.stop(true); - }, - startDrag: function(e) { - this.dragging = true; - // - this.my = e.pageY; - this.py = this.uy = this.y; - // - this.mx = e.pageX; - this.px = this.ux = this.x; - }, - drag: function(e) { - if (this.dragging) { - var dy = this.vertical ? e.pageY - this.my : 0; - this.uy = dy + this.py; - // provides resistance against dragging into overscroll - this.uy = this.boundaryDamping(this.uy, this.topBoundary, this.bottomBoundary, this.kDragDamping); - // - var dx = this.horizontal ? e.pageX - this.mx : 0; - this.ux = dx + this.px; - // provides resistance against dragging into overscroll - this.ux = this.boundaryDamping(this.ux, this.leftBoundary, this.rightBoundary, this.kDragDamping); - // - this.start(); - return true; - } - }, - dragDrop: function(e) { - if (this.dragging && !window.PalmSystem) { - var kSimulatedFlickScalar = 0.5; - this.y = this.uy; - this.y0 = this.y - (this.y - this.y0) * kSimulatedFlickScalar; - this.x = this.ux; - this.x0 = this.x - (this.x - this.x0) * kSimulatedFlickScalar; - } - this.dragFinish(); - }, - dragFinish: function() { - this.dragging = false; - }, - flick: function(e) { - var v; - if (this.vertical) { - v = e.yVelocity > 0 ? Math.min(this.kMaxFlick, e.yVelocity) : Math.max(-this.kMaxFlick, e.yVelocity); - this.y = this.y0 + v * this.kFlickScalar; - } - if (this.horizontal) { - v = e.xVelocity > 0 ? Math.min(this.kMaxFlick, e.xVelocity) : Math.max(-this.kMaxFlick, e.xVelocity); - this.x = this.x0 + v * this.kFlickScalar; - } - this.start(); - }, - mousewheel: function(e) { - var dy = this.vertical ? e.wheelDeltaY || e.wheelDelta: 0; - if ((dy > 0 && this.y < this.topBoundary) || (dy < 0 && this.y > this.bottomBoundary)) { - this.stop(true); - this.y = this.y0 = this.y0 + dy; - this.start(); - return true; - } - }, - scroll: function() { - this.doScroll(); - }, - // NOTE: Yip/Orvell method for determining scroller instantaneous velocity - // FIXME: incorrect if called when scroller is in overscroll region - // because does not account for additional overscroll damping. - /** - Animates a scroll to the specified position. - */ - scrollTo: function(inX, inY) { - if (inY !== null) { - this.y = this.y0 - (inY + this.y0) * (1 - this.kFrictionDamping); - } - if (inX !== null) { - this.x = this.x0 - (inX + this.x0) * (1 - this.kFrictionDamping); - } - this.start(); - }, - setScrollX: function(inX) { - this.x = this.x0 = inX; - }, - setScrollY: function(inY) { - this.y = this.y0 = inY; - }, - setScrollPosition: function(inPosition) { - this.setScrollY(inPosition); - }, - isScrolling: function() { - return Boolean(this.job); - }, - isInOverScroll: function() { - return this.job && (this.x > this.leftBoundary || this.x < this.rightBoundary || - this.y > this.topBoundary || this.y < this.bottomBoundary); - } -}); diff --git a/enyo/source/touch/ScrollStrategy.js b/enyo/source/touch/ScrollStrategy.js deleted file mode 100644 index 4e39207..0000000 --- a/enyo/source/touch/ScrollStrategy.js +++ /dev/null @@ -1,186 +0,0 @@ -/** - _enyo.ScrollStrategy_ is a helper kind that implements a default scrolling - strategy for an enyo.Scroller. - - _enyo.ScrollStrategy_ is not typically created in application code. - Instead, it is specified as the value of the `strategyKind` property of an - `enyo.Scroller` or enyo.List, or is used by the - framework implicitly. -*/ -enyo.kind({ - name: "enyo.ScrollStrategy", - tag: null, - published: { - /** - Specifies how to vertically scroll. Acceptable values are: - - * "scroll": Always shows a scrollbar; sets _overflow: scroll_. - * "auto": Scrolls only if needed; sets _overflow: auto_. - * "hidden": Never scrolls; sets _overflow: hidden_. - * "default": Same as "auto". - */ - vertical: "default", - /** - Specifies how to horizontally scroll. Acceptable values are: - - * "scroll": Always shows a scrollbar; sets _overflow: scroll_. - * "auto": Scrolls only if needed; sets _overflow: auto_. - * "hidden": Never scrolls; sets _overflow: hidden_. - * "default": Same as "auto". - */ - horizontal: "default", - //* Scroll position along horizontal axis - scrollLeft: 0, - //* Scroll position along vertical axis - scrollTop: 0, - //* Maximum height of scroll content - maxHeight: null - }, - //* @protected - handlers: { - ondragstart: "dragstart", - ondragfinish: "dragfinish", - ondown: "down", - onmove: "move" - }, - create: function() { - this.inherited(arguments); - this.horizontalChanged(); - this.verticalChanged(); - this.maxHeightChanged(); - }, - rendered: function() { - this.inherited(arguments); - enyo.makeBubble(this.container, "scroll"); - this.scrollNode = this.calcScrollNode(); - }, - teardownRender: function() { - this.inherited(arguments); - this.scrollNode = null; - }, - calcScrollNode: function() { - return this.container.hasNode(); - }, - horizontalChanged: function() { - this.container.applyStyle("overflow-x", this.horizontal == "default" ? "auto" : this.horizontal); - }, - verticalChanged: function() { - this.container.applyStyle("overflow-y", this.vertical == "default" ? "auto" : this.vertical); - }, - maxHeightChanged: function() { - this.container.applyStyle("max-height", this.maxHeight); - }, - scrollTo: function(inX, inY) { - if (this.scrollNode) { - this.setScrollLeft(inX); - this.setScrollTop(inY); - } - }, - scrollToNode: function(inNode, inAlignWithTop) { - if (this.scrollNode) { - var sb = this.getScrollBounds(); - var n = inNode; - var b = {height: n.offsetHeight, width: n.offsetWidth, top: 0, left: 0}; - while (n && n.parentNode && n.id != this.scrollNode.id) { - b.top += n.offsetTop; - b.left += n.offsetLeft; - n = n.parentNode; - } - // By default, the element is scrolled to align with the top of the scroll area. - this.setScrollTop(Math.min(sb.maxTop, inAlignWithTop === false ? b.top - sb.clientHeight + b.height : b.top)); - this.setScrollLeft(Math.min(sb.maxLeft, inAlignWithTop === false ? b.left - sb.clientWidth + b.width : b.left)); - } - }, - scrollIntoView: function(inControl, inAlignWithTop) { - if (inControl.hasNode()) { - inControl.node.scrollIntoView(inAlignWithTop); - } - }, - isInView: function(inNode) { - var sb = this.getScrollBounds(); - var ot = inNode.offsetTop; - var oh = inNode.offsetHeight; - var ol = inNode.offsetLeft; - var ow = inNode.offsetWidth; - return (ot >= sb.top && ot + oh <= sb.top + sb.clientHeight) && (ol >= sb.left && ol + ow <= sb.left + sb.clientWidth); - }, - setScrollTop: function(inTop) { - this.scrollTop = inTop; - if (this.scrollNode) { - this.scrollNode.scrollTop = this.scrollTop; - } - }, - setScrollLeft: function(inLeft) { - this.scrollLeft = inLeft; - if (this.scrollNode) { - this.scrollNode.scrollLeft = this.scrollLeft; - } - }, - getScrollLeft: function() { - return this.scrollNode ? this.scrollNode.scrollLeft : this.scrollLeft; - }, - getScrollTop: function() { - return this.scrollNode ? this.scrollNode.scrollTop : this.scrollTop; - }, - _getScrollBounds: function() { - var s = this.getScrollSize(), cn = this.container.hasNode(); - var b = { - left: this.getScrollLeft(), - top: this.getScrollTop(), - clientHeight: cn ? cn.clientHeight : 0, - clientWidth: cn ? cn.clientWidth : 0, - height: s.height, - width: s.width - }; - b.maxLeft = Math.max(0, b.width - b.clientWidth); - b.maxTop = Math.max(0, b.height - b.clientHeight); - return b; - }, - getScrollSize: function() { - var n = this.scrollNode; - return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; - }, - getScrollBounds: function() { - return this._getScrollBounds(); - }, - calcStartInfo: function() { - var sb = this.getScrollBounds(); - var y = this.getScrollTop(), x = this.getScrollLeft(); - this.canVertical = sb.maxTop > 0 && this.vertical != "hidden"; - this.canHorizontal = sb.maxLeft > 0 && this.horizontal != "hidden"; - this.startEdges = { - top: y === 0, - bottom: y === sb.maxTop, - left: x === 0, - right: x === sb.maxLeft - }; - }, - // NOTE: down, move, and drag handlers are needed only for native touch scrollers - shouldDrag: function(inEvent) { - var requestV = inEvent.vertical; - return (requestV && this.canVertical || !requestV && this.canHorizontal) /*&& !this.isOobVerticalScroll(inEvent)*/; - }, - dragstart: function(inSender, inEvent) { - this.dragging = this.shouldDrag(inEvent); - if (this.dragging) { - return this.preventDragPropagation; - } - }, - dragfinish: function(inSender, inEvent) { - if (this.dragging) { - this.dragging = false; - inEvent.preventTap(); - } - }, - // avoid allowing scroll when starting at a vertical boundary to prevent ios from window scrolling. - down: function(inSender, inEvent) { - this.calcStartInfo(); - }, - // NOTE: mobile native scrollers need touchmove. Indicate this by - // setting the requireTouchmove property to true. - move: function(inSender, inEvent) { - if (inEvent.which && (this.canVertical && inEvent.vertical || this.canHorizontal && inEvent.horizontal)) { - inEvent.disablePrevention(); - } - } -}); \ No newline at end of file diff --git a/enyo/source/touch/Scroller.css b/enyo/source/touch/Scroller.css deleted file mode 100644 index 2390c92..0000000 --- a/enyo/source/touch/Scroller.css +++ /dev/null @@ -1,19 +0,0 @@ -.enyo-scroller { - position: relative; -} - -.enyo-fit.enyo-scroller { - position: absolute; -} - -.enyo-touch-scroller { - overflow: hidden; -} - -.enyo-touch-strategy-container { - overflow: hidden; -} - -.enyo-scrollee-fit { - height: 100%; -} \ No newline at end of file diff --git a/enyo/source/touch/Scroller.js b/enyo/source/touch/Scroller.js deleted file mode 100644 index 81f69d5..0000000 --- a/enyo/source/touch/Scroller.js +++ /dev/null @@ -1,344 +0,0 @@ -/** -_enyo.Scroller_ is a scroller suitable for use in both desktop and mobile -applications. - -In some mobile environments, a default scrolling solution is not implemented for -DOM elements. In such cases, _enyo.Scroller_ implements a touch-based scrolling -solution, which may be opted into either globally (by setting the flag -_enyo.Scroller.touchScrolling = true;_) or on a per-instance basis (by -specifying a _strategyKind_ of "TouchScrollStrategy"). - -For more information, see the documentation on -[Scrollers](https://github.com/enyojs/enyo/wiki/Scrollers) in the Enyo Developer -Guide. -*/ -enyo.kind({ - name: "enyo.Scroller", - published: { - /** - Specifies how to horizontally scroll. Acceptable values are - "scroll", "auto," "hidden," and "default". The precise - effect of the setting is determined by the scroll strategy. - */ - horizontal: "default", - /** - Specifies how to vertically scroll. Acceptable values are "scroll", - "auto," "hidden," and "default". The precise effect of the setting - is determined by the scroll strategy. - */ - vertical: "default", - /** - The vertical scroll position - */ - scrollTop: 0, - /** - The horizontal scroll position - */ - scrollLeft: 0, - /** - Maximum height of the scroll content - */ - maxHeight: null, - /** - Set to true to make this scroller select a platform-appropriate - touch-based scrolling strategy. Note that if you specify a value for - _strategyKind_, that will take precedence over this setting. - */ - touch: false, - /** - Specifies a type of scrolling. The scroller will attempt to - automatically select a strategy compatible with the runtime - environment. Alternatively, you may choose to use a specific - strategy: - - * ScrollStrategy is the default - and implements no scrolling, relying instead on the environment - to scroll properly. - - * TouchScrollStrategy - implements a touch scrolling mechanism. - - * TranslateScrollStrategy - implements a touch scrolling mechanism using translations; it is - currently recommended only for Android 3 and 4 & Windows Phone 8. - - * TransitionScrollStrategy - implements a touch scrolling mechanism using CSS transitions; it is - currently recommended only for iOS 5 and later. - */ - strategyKind: "ScrollStrategy", - //* Set to true to display a scroll thumb in touch scrollers - thumb: true - }, - events: { - //* Fires when a scrolling action starts. - onScrollStart: "", - //* Fires while a scrolling action is in progress. - onScroll: "", - //* Fires when a scrolling action stops. - onScrollStop: "" - }, - /** - If true (the default) and a touch scroller, the scroller will overscroll - and bounce back at the edges - */ - touchOverscroll: true, - /** - If true (the default), the scroller will not propagate _dragstart_ - events that cause it to start scrolling - */ - preventDragPropagation: true, - /** - If true, the scroller will not propagate scroll events - */ - preventScrollPropagation: true, - //* @protected - handlers: { - onscroll: "domScroll", - onScrollStart: "scrollStart", - onScroll: "scroll", - onScrollStop: "scrollStop" - }, - classes: "enyo-scroller", - statics: { - osInfo: [ - {os: "android", version: 3}, - {os: "androidChrome", version: 18}, - {os: "androidFirefox", version: 16}, - {os: "firefoxOS", version: 16}, - {os: "ios", version: 5}, - {os: "webos", version: 1e9}, - {os: "blackberry", version:1e9} - ], - //* Returns true if platform should have touch events. - hasTouchScrolling: function() { - for (var i=0, t, m; (t=this.osInfo[i]); i++) { - if (enyo.platform[t.os]) { - return true; - } - } - // special detection for IE10+ on touch devices - if ((enyo.platform.ie >= 10 || enyo.platform.windowsPhone >= 8) && enyo.platform.touch) { - return true; - } - }, - /** - Returns true if the platform has native div scrollers (desktop - browsers always have them). - */ - hasNativeScrolling: function() { - for (var i=0, t, m; (t=this.osInfo[i]); i++) { - if (enyo.platform[t.os] < t.version) { - return false; - } - } - return true; - }, - getTouchStrategy: function() { - return (enyo.platform.android >= 3) || (enyo.platform.windowsPhone === 8) - ? "TranslateScrollStrategy" - : "TouchScrollStrategy"; - } - }, - controlParentName: "strategy", - create: function() { - this.inherited(arguments); - this.horizontalChanged(); - this.verticalChanged(); - }, - importProps: function(inProps) { - this.inherited(arguments); - // allow global overriding of strategy kind - if (inProps && inProps.strategyKind === undefined && (enyo.Scroller.touchScrolling || this.touch)) { - this.strategyKind = enyo.Scroller.getTouchStrategy(); - } - }, - initComponents: function() { - this.strategyKindChanged(); - this.inherited(arguments); - }, - teardownChildren: function() { - this.cacheScrollPosition(); - this.inherited(arguments); - }, - rendered: function() { - this.inherited(arguments); - this.restoreScrollPosition(); - }, - strategyKindChanged: function() { - if (this.$.strategy) { - this.$.strategy.destroy(); - this.controlParent = null; - } - // note: createComponents automatically updates controlParent. - this.createStrategy(); - if (this.hasNode()) { - this.render(); - } - }, - createStrategy: function() { - this.createComponents([{name: "strategy", maxHeight: this.maxHeight, - kind: this.strategyKind, thumb: this.thumb, - preventDragPropagation: this.preventDragPropagation, - overscroll:this.touchOverscroll, isChrome: true}]); - }, - getStrategy: function() { - return this.$.strategy; - }, - maxHeightChanged: function() { - this.$.strategy.setMaxHeight(this.maxHeight); - }, - showingChanged: function() { - if (!this.showing) { - this.cacheScrollPosition(); - this.setScrollLeft(0); - this.setScrollTop(0); - } - this.inherited(arguments); - if (this.showing) { - this.restoreScrollPosition(); - } - }, - thumbChanged: function() { - this.$.strategy.setThumb(this.thumb); - }, - cacheScrollPosition: function() { - this.cachedPosition = {left: this.getScrollLeft(), top: this.getScrollTop()}; - }, - restoreScrollPosition: function() { - if (this.cachedPosition) { - this.setScrollLeft(this.cachedPosition.left); - this.setScrollTop(this.cachedPosition.top); - this.cachedPosition = null; - } - }, - horizontalChanged: function() { - this.$.strategy.setHorizontal(this.horizontal); - }, - verticalChanged: function() { - this.$.strategy.setVertical(this.vertical); - }, - // FIXME: these properties are virtual; property changed methods are fired only if - // property value changes, not if getter changes. - //* Sets scroll position along horizontal axis. - setScrollLeft: function(inLeft) { - this.scrollLeft = inLeft; - this.$.strategy.setScrollLeft(this.scrollLeft); - }, - //* Sets scroll position along vertical axis. - setScrollTop: function(inTop) { - this.scrollTop = inTop; - this.$.strategy.setScrollTop(inTop); - }, - //* Gets scroll position along horizontal axis. - getScrollLeft: function() { - return this.$.strategy.getScrollLeft(); - }, - //* Gets scroll position along vertical axis. - getScrollTop: function() { - return this.$.strategy.getScrollTop(); - }, - //* @public - /** - Returns an object describing the scroll boundaries with _height_ and - _width_ properties. - */ - getScrollBounds: function() { - return this.$.strategy.getScrollBounds(); - }, - /** - Scrolls the given control (_inControl_) into view. If _inAlignWithTop_ - is true, _inControl_ is aligned with the top of the scroller. - */ - scrollIntoView: function(inControl, inAlignWithTop) { - this.$.strategy.scrollIntoView(inControl, inAlignWithTop); - }, - //* Scrolls to the position specified by _inX_ and _inY_ in pixel units. - scrollTo: function(inX, inY) { - this.$.strategy.scrollTo(inX, inY); - }, - /** - Ensures that the given control is visible in the scroller's viewport. - Unlike _scrollIntoView_, which uses DOM's _scrollIntoView_, this only - affects the current scroller. - */ - scrollToControl: function(inControl, inAlignWithTop) { - this.scrollToNode(inControl.hasNode(), inAlignWithTop); - }, - //* Ensures that the given node is visible in the scroller's viewport. - scrollToNode: function(inNode, inAlignWithTop) { - this.$.strategy.scrollToNode(inNode, inAlignWithTop); - }, - //* @protected - //* Normalizes scroll event to _onScroll_. - domScroll: function(inSender, e) { - // if a scroll event originated here, pass it to our strategy to handle - if (this.$.strategy.domScroll && e.originator == this) { - this.$.strategy.scroll(inSender, e); - } - this.doScroll(e); - return true; - }, - /** - Returns true if the current scroll event should be stopped; false if it - should be allowed to propagate. - */ - shouldStopScrollEvent: function(inEvent) { - return (this.preventScrollPropagation && - inEvent.originator.owner != this.$.strategy); - }, - /** - Calls _shouldStopScrollEvent_ to determine whether current scroll event - should be stopped. - */ - scrollStart: function(inSender, inEvent) { - return this.shouldStopScrollEvent(inEvent); - }, - //* Either propagates or stops the current scroll event. - scroll: function(inSender, inEvent) { - // note: scroll event can be native dom or generated. - if (inEvent.dispatchTarget) { - // allow a dom event if it orignated with this scroller or its strategy - return this.preventScrollPropagation && !(inEvent.originator == this || - inEvent.originator.owner == this.$.strategy); - } else { - return this.shouldStopScrollEvent(inEvent); - } - }, - /** - Calls _shouldStopScrollEvent_ to determine whether current scroll event - should be stopped. - */ - scrollStop: function(inSender, inEvent) { - return this.shouldStopScrollEvent(inEvent); - }, - //* @public - //* Scroll to the top of the scrolling region. - scrollToTop: function() { - this.setScrollTop(0); - }, - //* Scroll to the bottom of the scrolling region. - scrollToBottom: function() { - this.setScrollTop(this.getScrollBounds().maxTop); - }, - //* Scroll to the right edge of the scrolling region. - scrollToRight: function() { - this.setScrollLeft(this.getScrollBounds().maxLeft); - }, - //* Scroll to the left edge of the scrolling region. - scrollToLeft: function() { - this.setScrollLeft(0); - }, - //* Ensures scroll position is in bounds. - stabilize: function() { - var s = this.getStrategy(); - if (s.stabilize) { - s.stabilize(); - } - } -}); - -// provide a touch scrolling solution by default when the environment is mobile -if (enyo.Scroller.hasTouchScrolling()) { - enyo.Scroller.prototype.strategyKind = enyo.Scroller.getTouchStrategy(); -} diff --git a/enyo/source/touch/Thumb.css b/enyo/source/touch/Thumb.css deleted file mode 100644 index 81e998f..0000000 --- a/enyo/source/touch/Thumb.css +++ /dev/null @@ -1,22 +0,0 @@ -.enyo-thumb { - position: absolute; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; - background: #333; - border: 1px solid #666; - opacity: 0.75; - z-index: 1; -} - -.enyo-vthumb { - top: 0; - right: 2px; - width: 4px; -} - -.enyo-hthumb { - left: 0; - bottom: 2px; - height: 4px; -} diff --git a/enyo/source/touch/Thumb.js b/enyo/source/touch/Thumb.js deleted file mode 100644 index 769919c..0000000 --- a/enyo/source/touch/Thumb.js +++ /dev/null @@ -1,111 +0,0 @@ -/** -_enyo.ScrollThumb_ is a helper kind used by -enyo.TouchScrollStrategy and -enyo.TranslateScrollStrategy to -display a small visual scroll indicator. - -_enyo.ScrollThumb_ is not typically created in application code. -*/ - -enyo.kind({ - name: "enyo.ScrollThumb", - //* The orientation of the scroll indicator bar; "v" for vertical or "h" for horizontal - axis: "v", - //* @protected - //* Minimum size of the indicator - minSize: 4, - //* Size of the corners of the indicator - cornerSize: 6, - classes: "enyo-thumb", - create: function() { - this.inherited(arguments); - var v = this.axis == "v"; - this.dimension = v ? "height" : "width"; - this.offset = v ? "top" : "left"; - this.translation = v ? "translateY" : "translateX"; - this.positionMethod = v ? "getScrollTop" : "getScrollLeft"; - this.sizeDimension = v ? "clientHeight" : "clientWidth"; - this.addClass("enyo-" + this.axis + "thumb"); - this.transform = enyo.dom.canTransform(); - if (enyo.dom.canAccelerate()) { - enyo.dom.transformValue(this, "translateZ", 0); - } - }, - //* Syncs the scroll indicator bar to the scroller size and position, - //* as determined by the passed-in scroll strategy. - sync: function(inStrategy) { - this.scrollBounds = inStrategy._getScrollBounds(); - this.update(inStrategy); - }, - update: function(inStrategy) { - if (this.showing) { - var d = this.dimension, o = this.offset; - var bd = this.scrollBounds[this.sizeDimension], sbd = this.scrollBounds[d]; - var overs = 0, overp = 0, over = 0; - if (bd >= sbd) { - this.hide(); - return; - } - if (inStrategy.isOverscrolling()) { - over = inStrategy.getOverScrollBounds()["over" + o]; - overs = Math.abs(over); - overp = Math.max(over, 0); - } - var sbo = inStrategy[this.positionMethod]() - over; - // calc size & position - var bdc = bd - this.cornerSize; - var s = Math.floor((bd * bd / sbd) - overs); - s = Math.max(this.minSize, s); - var p = Math.floor((bdc * sbo / sbd) + overp); - p = Math.max(0, Math.min(bdc - this.minSize, p)); - // apply thumb styling - this.needed = s < bd; - if (this.needed && this.hasNode()) { - if (this._pos !== p) { - this._pos = p; - if(!this.transform) { - //adjust top/left for browsers that don't support translations - if(this.axis=="v") { - this.setBounds({top:p + "px"}); - } else { - this.setBounds({left:p + "px"}); - } - } else { - enyo.dom.transformValue(this, this.translation, p + "px"); - } - } - if (this._size !== s) { - this._size = s; - this.node.style[d] = this.domStyles[d] = s + "px"; - } - } else { - this.hide(); - } - } - }, - // implement set because showing is not changed while - // we delayHide but we want to cancel the hide. - setShowing: function(inShowing) { - if (inShowing && inShowing != this.showing) { - if (this.scrollBounds[this.sizeDimension] >= this.scrollBounds[this.dimension]) { - return; - } - } - if (this.hasNode()) { - this.cancelDelayHide(); - } - if (inShowing != this.showing) { - var last = this.showing; - this.showing = inShowing; - this.showingChanged(last); - } - }, - delayHide: function(inDelay) { - if (this.showing) { - enyo.job(this.id + "hide", enyo.bind(this, "hide"), inDelay || 0); - } - }, - cancelDelayHide: function() { - enyo.job.stop(this.id + "hide"); - } -}); diff --git a/enyo/source/touch/TouchScrollStrategy.js b/enyo/source/touch/TouchScrollStrategy.js deleted file mode 100644 index 9bbe930..0000000 --- a/enyo/source/touch/TouchScrollStrategy.js +++ /dev/null @@ -1,429 +0,0 @@ -/** - _enyo.TouchScrollStrategy_ is a helper kind for implementing a touch-based - scroller. It integrates the scrolling simulation provided by - enyo.ScrollMath into an - enyo.Scroller. - - _enyo.TouchScrollStrategy_ is not typically created in application code. - Instead, it is specified as the value of the `strategyKind` property of an - `enyo.Scroller` or enyo.List, or is used by the - framework implicitly. -*/ -enyo.kind({ - name: "enyo.TouchScrollStrategy", - kind: "ScrollStrategy", - /** - If true (the default), the scroller will overscroll and bounce back at the edges - */ - overscroll: true, - /** - If true (the default), the scroller will not propagate _dragstart_ - events that cause it to start scrolling - */ - preventDragPropagation: true, - published: { - /** - Specifies how to vertically scroll. Acceptable values are: - - * "scroll": Always scroll. - * "auto": Scroll only if the content overflows the scroller. - * "hidden": Never scroll. - * "default": In touch environments, the default vertical scrolling - behavior is to always scroll. If the content does not overflow - the scroller, the scroller will overscroll and snap back. - */ - vertical: "default", - /** - Specifies how to horizontally scroll. Acceptable values are: - - * "scroll": Always scroll. - * "auto": Scroll only if the content overflows the scroller. - * "hidden": Never scroll. - * "default": Same as "auto". - */ - horizontal: "default", - //* Set to true to display a scroll thumb - thumb: true, - /** - Set to true to display a transparent overlay while scrolling. This - can help improve performance of complex, large scroll regions on - some platforms (e.g., Android). - */ - scrim: false, - //* Allow drag events sent when gesture events are happening simultaneously - dragDuringGesture: true - }, - events: { - onShouldDrag: "" - }, - //* @protected - handlers: { - onscroll: "domScroll", - onflick: "flick", - onhold: "hold", - ondragstart: "dragstart", - onShouldDrag: "shouldDrag", - ondrag: "drag", - ondragfinish: "dragfinish", - onmousewheel: "mousewheel" - }, - tools: [ - {kind: "ScrollMath", onScrollStart: "scrollMathStart", onScroll: "scrollMathScroll", onScrollStop: "scrollMathStop"}, - {name: "vthumb", kind: "ScrollThumb", axis: "v", showing: false}, - {name: "hthumb", kind: "ScrollThumb", axis: "h", showing: false} - ], - scrimTools: [{name: "scrim", classes: "enyo-fit", style: "z-index: 1;", showing: false}], - components: [ - {name: "client", classes: "enyo-touch-scroller"} - ], - // flag telling us whether the list is currently reordering - listReordering: false, - create: function() { - this.inherited(arguments); - this.transform = enyo.dom.canTransform(); - if(!this.transform) { - if(this.overscroll) { - //so we can adjust top/left if browser can't handle translations - this.$.client.applyStyle("position", "relative"); - } - } - this.accel = enyo.dom.canAccelerate(); - var containerClasses = "enyo-touch-strategy-container"; - // note: needed for ios to avoid incorrect clipping of thumb - // and need to avoid on Android as it causes problems hiding the thumb - if (enyo.platform.ios && this.accel) { - containerClasses += " enyo-composite"; - } - this.scrimChanged(); - this.container.addClass(containerClasses); - this.translation = this.accel ? "translate3d" : "translate"; - }, - initComponents: function() { - this.createChrome(this.tools); - this.inherited(arguments); - }, - destroy: function() { - this.container.removeClass("enyo-touch-strategy-container"); - this.inherited(arguments); - }, - rendered: function() { - this.inherited(arguments); - enyo.makeBubble(this.$.client, "scroll"); - this.calcBoundaries(); - this.syncScrollMath(); - if (this.thumb) { - this.alertThumbs(); - } - }, - scrimChanged: function() { - if (this.scrim && !this.$.scrim) { - this.makeScrim(); - } - if (!this.scrim && this.$.scrim) { - this.$.scrim.destroy(); - } - }, - makeScrim: function() { - // reset control parent so scrim doesn't go into client. - var cp = this.controlParent; - this.controlParent = null; - this.createChrome(this.scrimTools); - this.controlParent = cp; - var cn = this.container.hasNode(); - // render scrim in container, strategy has no dom. - if (cn) { - this.$.scrim.parentNode = cn; - this.$.scrim.render(); - } - }, - //* Whether or not the scroller is actively moving - isScrolling: function() { - var m = this.$.scrollMath; - return m ? m.isScrolling() : this.scrolling; - }, - //* Whether or not the scroller is in overscrolling - isOverscrolling: function() { - var m = this.$.scrollMath || this; - return (this.overscroll) ? m.isInOverScroll() : false; - }, - domScroll: function() { - if (!this.isScrolling()) { - this.calcBoundaries(); - this.syncScrollMath(); - if (this.thumb) { - this.alertThumbs(); - } - } - }, - horizontalChanged: function() { - this.$.scrollMath.horizontal = (this.horizontal != "hidden"); - }, - verticalChanged: function() { - this.$.scrollMath.vertical = (this.vertical != "hidden"); - }, - maxHeightChanged: function() { - this.$.client.applyStyle("max-height", this.maxHeight); - // note: previously used enyo-fit here but IE would reset scroll position when the scroll thumb - // was hidden; in general IE resets scrollTop when there are 2 abs position siblings, one has - // scrollTop and the other is hidden. - this.$.client.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); - }, - thumbChanged: function() { - this.hideThumbs(); - }, - stop: function() { - if (this.isScrolling()) { - this.$.scrollMath.stop(true); - } - }, - stabilize: function() { - if(this.$.scrollMath) { - this.$.scrollMath.stabilize(); - } - }, - //* Scrolls to specific x/y positions within the scroll area. - scrollTo: function(inX, inY) { - this.stop(); - this.$.scrollMath.scrollTo(inX, inY || inY === 0 ? inY : null); - }, - scrollIntoView: function() { - this.stop(); - this.inherited(arguments); - }, - //* Sets the left scroll position within the scroller. - setScrollLeft: function() { - this.stop(); - this.inherited(arguments); - }, - //* Sets the top scroll position within the scroller. - setScrollTop: function() { - this.stop(); - this.inherited(arguments); - }, - //* Gets the left scroll position within the scroller. - getScrollLeft: function() { - return this.isScrolling() ? this.scrollLeft : this.inherited(arguments); - }, - //* Gets the top scroll position within the scroller. - getScrollTop: function() { - return this.isScrolling() ? this.scrollTop : this.inherited(arguments); - }, - calcScrollNode: function() { - return this.$.client.hasNode(); - }, - calcAutoScrolling: function() { - var v = (this.vertical == "auto"); - var h = (this.horizontal == "auto") || (this.horizontal == "default"); - if ((v || h) && this.scrollNode) { - var b = this.getScrollBounds(); - if (v) { - this.$.scrollMath.vertical = b.height > b.clientHeight; - } - if (h) { - this.$.scrollMath.horizontal = b.width > b.clientWidth; - } - } - }, - shouldDrag: function(inSender, e) { - this.calcAutoScrolling(); - var requestV = e.vertical; - var canH = this.$.scrollMath.horizontal && !requestV; - var canV = this.$.scrollMath.vertical && requestV; - var down = e.dy < 0, right = e.dx < 0; - var oobV = (!down && this.startEdges.top || down && this.startEdges.bottom); - var oobH = (!right && this.startEdges.left || right && this.startEdges.right); - // we would scroll if not at a boundary - if (!e.boundaryDragger && (canH || canV)) { - e.boundaryDragger = this; - } - // include boundary exclusion - if ((!oobV && canV) || (!oobH && canH)) { - e.dragger = this; - return true; - } - }, - flick: function(inSender, e) { - var onAxis = Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.$.scrollMath.horizontal : this.$.scrollMath.vertical; - if (onAxis && this.dragging) { - this.$.scrollMath.flick(e); - return this.preventDragPropagation; - } - }, - hold: function(inSender, e) { - if (this.isScrolling() && !this.isOverscrolling()) { - var m = this.$.scrollMath || this; - m.stop(e); - return true; - } - }, - move: function(inSender, inEvent) { - }, - // Special synthetic DOM events served up by the Gesture system - dragstart: function(inSender, inEvent) { - // Ignore drags sent from multi-touch events - if(!this.dragDuringGesture && inEvent.srcEvent.touches && inEvent.srcEvent.touches.length > 1) { - return true; - } - // note: allow drags to propagate to parent scrollers via data returned in the shouldDrag event. - this.doShouldDrag(inEvent); - this.dragging = (inEvent.dragger == this || (!inEvent.dragger && inEvent.boundaryDragger == this)); - if (this.dragging) { - inEvent.preventDefault(); - // note: needed because show/hide changes - // the position so sync'ing is required when - // dragging begins (needed because show/hide does not trigger onscroll) - this.syncScrollMath(); - this.$.scrollMath.startDrag(inEvent); - if (this.preventDragPropagation) { - return true; - } - } - }, - drag: function(inSender, inEvent) { - // if the list is doing a reorder, don't scroll - if(this.listReordering) { - return false; - } - if (this.dragging) { - inEvent.preventDefault(); - this.$.scrollMath.drag(inEvent); - if (this.scrim) { - this.$.scrim.show(); - } - } - }, - dragfinish: function(inSender, inEvent) { - if (this.dragging) { - inEvent.preventTap(); - this.$.scrollMath.dragFinish(); - this.dragging = false; - if (this.scrim) { - this.$.scrim.hide(); - } - } - }, - mousewheel: function(inSender, e) { - if (!this.dragging) { - this.calcBoundaries(); - this.syncScrollMath(); - this.stabilize(); - if (this.$.scrollMath.mousewheel(e)) { - e.preventDefault(); - return true; - } - } - }, - scrollMathStart: function(inSender) { - if (this.scrollNode) { - this.calcBoundaries(); - if (this.thumb) { - this.showThumbs(); - } - } - }, - scrollMathScroll: function(inSender) { - if(!this.overscroll) { - //don't overscroll past edges - this.effectScroll(-Math.min(inSender.leftBoundary, Math.max(inSender.rightBoundary, inSender.x)), - -Math.min(inSender.topBoundary, Math.max(inSender.bottomBoundary, inSender.y))); - } else { - this.effectScroll(-inSender.x, -inSender.y); - } - if (this.thumb) { - this.updateThumbs(); - } - }, - scrollMathStop: function(inSender) { - this.effectScrollStop(); - if (this.thumb) { - this.delayHideThumbs(100); - } - }, - calcBoundaries: function() { - var s = this.$.scrollMath || this, b = this._getScrollBounds(); - s.bottomBoundary = b.clientHeight - b.height; - s.rightBoundary = b.clientWidth - b.width; - }, - syncScrollMath: function() { - var m = this.$.scrollMath; - if(m) { - m.setScrollX(-this.getScrollLeft()); - m.setScrollY(-this.getScrollTop()); - } - }, - effectScroll: function(inX, inY) { - if (this.scrollNode) { - this.scrollLeft = this.scrollNode.scrollLeft = inX; - this.scrollTop = this.scrollNode.scrollTop = inY; - this.effectOverscroll(Math.round(inX), Math.round(inY)); - } - }, - effectScrollStop: function() { - this.effectOverscroll(null, null); - }, - effectOverscroll: function(inX, inY) { - var n = this.scrollNode; - var x = "0", y = "0", z = this.accel ? ",0" : ""; - if (inY !== null && Math.abs(inY - n.scrollTop) > 1) { - y = (n.scrollTop - inY); - } - if (inX !== null && Math.abs(inX - n.scrollLeft) > 1) { - x = (n.scrollLeft - inX); - } - if(!this.transform) { - //adjust top/left if browser can't handle translations - this.$.client.setBounds({left:x + "px", top:y + "px"}); - } else { - enyo.dom.transformValue(this.$.client, this.translation, x + "px, " + y + "px" + z); - } - }, - //* Returns the values of _overleft_ and _overtop_, if any. - getOverScrollBounds: function() { - var m = this.$.scrollMath || this; - return { - overleft: Math.min(m.leftBoundary - m.x, 0) || Math.max(m.rightBoundary - m.x, 0), - overtop: Math.min(m.topBoundary - m.y, 0) || Math.max(m.bottomBoundary - m.y, 0) - }; - }, - _getScrollBounds: function() { - var r = this.inherited(arguments); - enyo.mixin(r, this.getOverScrollBounds()); - return r; - }, - getScrollBounds: function() { - this.stop(); - return this.inherited(arguments); - }, - // Thumb processing - alertThumbs: function() { - this.showThumbs(); - this.delayHideThumbs(500); - }, - //* Syncs the vertical and horizontal scroll indicators. - syncThumbs: function() { - this.$.vthumb.sync(this); - this.$.hthumb.sync(this); - }, - updateThumbs: function() { - this.$.vthumb.update(this); - this.$.hthumb.update(this); - }, - //* Syncs and shows both the vertical and horizontal scroll indicators. - showThumbs: function() { - this.syncThumbs(); - if (this.horizontal != "hidden") - this.$.hthumb.show(); - if (this.vertical != "hidden") - this.$.vthumb.show(); - }, - //* Hides the vertical and horizontal scroll indicators. - hideThumbs: function() { - this.$.vthumb.hide(); - this.$.hthumb.hide(); - }, - //* Hides the vertical and horizontal scroll indicators asynchronously. - delayHideThumbs: function(inDelay) { - this.$.vthumb.delayHide(inDelay); - this.$.hthumb.delayHide(inDelay); - } -}); diff --git a/enyo/source/touch/TransitionScrollStrategy.js b/enyo/source/touch/TransitionScrollStrategy.js deleted file mode 100644 index 92e56a6..0000000 --- a/enyo/source/touch/TransitionScrollStrategy.js +++ /dev/null @@ -1,616 +0,0 @@ -/** - _enyo.TransitionScrollStrategy_ is a helper kind that extends - enyo.TouchScrollStrategy, optimizing - it for scrolling environments in which effecting scroll changes with - transforms using CSS transitions is fastest. - - _enyo.TransitionScrollStrategy_ is not typically created in application code. - Instead, it is specified as the value of the `strategyKind` property of an - `enyo.Scroller` or enyo.List, or is used by the - framework implicitly. -*/ -enyo.kind({ - name: "enyo.TransitionScrollStrategy", - kind: "enyo.TouchScrollStrategy", - //* @protected - components: [ - {name: "clientContainer", classes: "enyo-touch-scroller", components: [ - {name: "client"} - ]} - ], - events: { - onScrollStart: "", - onScroll: "", - onScrollStop: "" - }, - handlers: { - ondown: "down", - ondragfinish: "dragfinish", - onwebkitTransitionEnd: "transitionComplete" - }, - //* No scrollMath tool for this strategy - tools: [ - {name: "vthumb", kind: "ScrollThumb", axis: "v", showing: true}, - {name: "hthumb", kind: "ScrollThumb", axis: "h", showing: false} - ], - //* Scalar applied to 'flick' event velocity - kFlickScalar: 600, - //* Top snap boundary, generally 0 - topBoundary: 0, - //* Right snap boundary, generally (viewport width - content width) - rightBoundary: 0, - //* Bottom snap boundary, generally (viewport height - content height) - bottomBoundary: 0, - //* Left snap boundary, generally 0 - leftBoundary: 0, - //* Flag to specify whether scrolling is in progress - scrolling: false, - //* Event listener for webkit transition completion - listener: null, - //* X Distance to scroll into overscroll space before bouncing back - boundaryX:0, - //* Y Distance to scroll into overscroll space before bouncing back - boundaryY:0, - //* Timeout used to stop scrolling on mousedown - stopTimeout: null, - //* MS delay used to stop scrolling on mousedown - stopTimeoutMS: 80, - //* Interval used to update scroll values and bubble scroll events during scroll animation - scrollInterval: null, - //* MS delay used to update scroll values and bubble scroll events during scroll animation - scrollIntervalMS: 50, - //* Transition animations - transitions: { - //* None - used for dragging, etc. - none : "", - //* Scroll - basic scrolling behavior - scroll : "3.8s cubic-bezier(.19,1,.28,1.0) 0s", - //* Bounce - overscroll bounceback behavior - bounce : "0.5s cubic-bezier(0.06,.5,.5,.94) 0s" - }, - - //* @public - - //* Sets the left scroll position within the scroller. - setScrollLeft: function(inLeft) { - var prevLeft = this.scrollLeft; - this.stop(); - this.scrollLeft = inLeft; - if(this.isInLeftOverScroll() || this.isInRightOverScroll()) { - this.scrollLeft = prevLeft; - } - this.effectScroll(); - }, - //* Sets the top scroll position within the scroller. - setScrollTop: function(inTop) { - var prevTop = this.scrollTop; - this.stop(); - this.scrollTop = inTop; - if(this.isInTopOverScroll() || this.isInBottomOverScroll()) { - this.scrollTop = prevTop; - } - this.effectScroll(); - }, - setScrollX: function(inLeft) { - this.scrollLeft = -1*inLeft; - }, - setScrollY: function(inTop) { - this.scrollTop = -1*inTop; - }, - - //* Gets the left scroll position within the scroller. - getScrollLeft: function() { - return this.scrollLeft; - }, - //* Gets the top scroll position within the scroller. - getScrollTop: function() { - return this.scrollTop; - }, - - //* @protected - - // apply initial transform so we're always composited - create: function() { - this.inherited(arguments); - enyo.dom.transformValue(this.$.client, this.translation, "0,0,0"); - }, - destroy: function() { - this.clearCSSTransitionInterval(); - this.inherited(arguments); - }, - getScrollSize: function() { - var n = this.$.client.hasNode(); - return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; - }, - horizontalChanged: function() { - if(this.horizontal == "hidden") { - this.scrollHorizontal = false; - } - }, - verticalChanged: function() { - if(this.vertical == "hidden") { - this.scrollVertical = false; - } - }, - calcScrollNode: function() { - return this.$.clientContainer.hasNode(); - }, - calcBoundaries: function() { - var b = this._getScrollBounds(); - this.bottomBoundary = b.clientHeight - b.height; - this.rightBoundary = b.clientWidth - b.width; - }, - maxHeightChanged: function() { - // content should cover scroller at a minimum if there's no max-height. - this.$.client.applyStyle("min-height", this.maxHeight ? null : "100%"); - this.$.client.applyStyle("max-height", this.maxHeight); - this.$.clientContainer.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); - }, - calcAutoScrolling: function() { - var b = this.getScrollBounds(); - if(this.vertical) { - this.scrollVertical = b.height > b.clientHeight; - } - if(this.horizontal) { - this.scrollHorizontal = b.width > b.clientWidth; - } - }, - isInOverScroll: function() { - return (this.isInTopOverScroll() || this.isInBottomOverScroll() || this.isInLeftOverScroll() || this.isInRightOverScroll()); - }, - isInLeftOverScroll: function() { - return (this.getScrollLeft() < this.leftBoundary); - }, - isInRightOverScroll: function() { - if(this.getScrollLeft <= 0) { - return false; - } else { - return (this.getScrollLeft()*-1 < this.rightBoundary); - } - }, - isInTopOverScroll: function() { - return (this.getScrollTop() < this.topBoundary); - }, - isInBottomOverScroll: function() { - if(this.getScrollTop() <= 0) { - return false; - } else { - return (this.getScrollTop()*-1 < this.bottomBoundary); - } - }, - calcStartInfo: function() { - var sb = this.getScrollBounds(), y = this.getScrollTop(), x = this.getScrollLeft(); - this.startEdges = { - top: y === 0, - bottom: y === sb.maxTop, - left: x === 0, - right: x === sb.maxLeft - }; - }, - mousewheel: function(inSender, e) { - if (!this.dragging) { - this.calcBoundaries(); - this.syncScrollMath(); - this.stabilize(); - var dy = this.vertical ? e.wheelDeltaY || e.wheelDelta : 0; - var y = parseFloat(this.getScrollTop()) + -1*parseFloat(dy); - y = (y*-1 < this.bottomBoundary) ? -1*this.bottomBoundary : (y < this.topBoundary) ? this.topBoundary : y; - this.setScrollTop(y); - this.doScroll(); - e.preventDefault(); - return true; - } - }, - // Update thumbs, recalculate boundaries, and bubble scroll event - scroll: function(inSender, inEvent) { - if(this.thumb) { - this.updateThumbs(); - } - this.calcBoundaries(); - this.doScroll(); - }, - // Scroll to current x,y coordinates and bubble scrollstart event - start: function() { - this.startScrolling(); - this.doScrollStart(); - }, - // If scrolling, stop. Hide thumbs and bubble scrollstop event. - stop: function() { - if(this.isScrolling()) { - this.stopScrolling(); - } - if (this.thumb) { - this.delayHideThumbs(100); - } - this.doScrollStop(); - }, - - // Set scroll x value to the current computed style - updateX: function() { - var x = window.getComputedStyle(this.$.client.node,null).getPropertyValue(enyo.dom.getCssTransformProp()).split('(')[1]; - x = (x == undefined) ? 0 : x.split(')')[0].split(',')[4]; - if(-1*parseFloat(x) === this.scrollLeft) { - return false; - } - this.scrollLeft = -1*parseFloat(x); - return true; - }, - // Set scroll y value to the current computed style - updateY: function() { - var y = window.getComputedStyle(this.$.client.node,null).getPropertyValue(enyo.dom.getCssTransformProp()).split('(')[1]; - y = (y == undefined) ? 0 : y.split(')')[0].split(',')[5]; - if(-1*parseFloat(y) === this.scrollTop) { - return false; - } - this.scrollTop = -1*parseFloat(y); - return true; - }, - // Apply transform to scroll the scroller - effectScroll: function() { - var o = (-1*this.scrollLeft) + "px, " + (-1*this.scrollTop) + "px" + (this.accel ? ", 0" : ""); - enyo.dom.transformValue(this.$.client, this.translation, o); - }, - // On touch, stop transition by setting transform values to current computed style, and - // changing transition time to 0s. TODO - down: function(inSender, inEvent) { - var _this = this; - if (this.isScrolling() && !this.isOverscrolling()) { - this.stopTimeout = setTimeout(function() { _this.stop(); }, this.stopTimeoutMS); - return true; - } - }, - // Special synthetic DOM events served up by the Gesture system - dragstart: function(inSender, inEvent) { - if(this.stopTimeout) { - clearTimeout(this.stopTimeout); - } - // Ignore drags sent from multi-touch events - if(!this.dragDuringGesture && inEvent.srcEvent.touches && inEvent.srcEvent.touches.length > 1) { - return true; - } - this.shouldDrag(inEvent); - this.dragging = (inEvent.dragger == this || (!inEvent.dragger && inEvent.boundaryDragger == this)); - if (this.dragging) { - if(this.isScrolling()) { - this.stopScrolling(); - } - if(this.thumb) { - this.showThumbs(); - } - inEvent.preventDefault(); - this.prevY = inEvent.pageY; - this.prevX = inEvent.pageX; - if (this.preventDragPropagation) { - return true; - } - } - }, - // Determine if we should allow dragging - shouldDrag: function(e) { - this.calcStartInfo(); - this.calcBoundaries(); - this.calcAutoScrolling(); - if(!this.scrollHorizontal) { - return this.shouldDragVertical(e); - } else { - if(!this.scrollVertical) { - return this.shouldDragHorizontal(e); - } else { - return (this.shouldDragVertical(e) || this.shouldDragHorizontal(e)); - } - } - }, - shouldDragVertical: function(e) { - var canV = this.canDragVertical(e); - var oobV = this.oobVertical(e); - // scroll if not at a boundary - if (!e.boundaryDragger && canV) { - e.boundaryDragger = this; - } - // include boundary exclusion - if (!oobV && canV) { - e.dragger = this; - return true; - } - }, - shouldDragHorizontal: function(e) { - var canH = this.canDragHorizontal(e); - var oobH = this.oobHorizontal(e); - // scroll if not at a boundary - if (!e.boundaryDragger && canH) { - e.boundaryDragger = this; - } - // include boundary exclusion - if (!oobH && canH) { - e.dragger = this; - return true; - } - }, - canDragVertical: function(e) { - return (this.scrollVertical && e.vertical); - }, - canDragHorizontal: function(e) { - return (this.scrollHorizontal && !e.vertical); - }, - oobVertical: function(e) { - var down = e.dy < 0; - return (!down && this.startEdges.top || down && this.startEdges.bottom); - }, - oobHorizontal: function(e) { - var right = e.dx < 0; - return (!right && this.startEdges.left || right && this.startEdges.right); - }, - // Move scroller based on user's dragging - drag: function(inSender, e) { - // if the list is doing a reorder, don't scroll - if(this.listReordering) { - return false; - } - // if shouldDrag() set this.dragging to true - if(this.dragging) { - e.preventDefault(); - // calculate new scroll values - this.scrollLeft = this.scrollHorizontal ? - this.calculateDragDistance(parseInt(this.getScrollLeft(), 10), (-1*(e.pageX-this.prevX)), this.leftBoundary, this.rightBoundary) : - this.getScrollLeft(); - this.scrollTop = this.scrollVertical ? - this.calculateDragDistance(this.getScrollTop(), (-1*(e.pageY-this.prevY)), this.topBoundary, this.bottomBoundary) : - this.getScrollTop(); - // apply new scroll values - this.effectScroll(); - this.scroll(); - // save values for next drag - this.prevY = e.pageY; - this.prevX = e.pageX; - this.resetBoundaryX(); - this.resetBoundaryY(); - } - }, - //* Figure how far the drag should go based on pointer movement (delta) - calculateDragDistance: function(currentPosition, delta, aBoundary, bBoundary) { - var newPosition = currentPosition + delta; - return this.overscrollDragDamping(currentPosition, newPosition,delta,aBoundary,bBoundary); - }, - //* Provides resistance against dragging into overscroll - overscrollDragDamping: function(currentPosition, newPosition, delta, aBoundary, bBoundary) { - if(newPosition < aBoundary || newPosition*-1 < bBoundary) { - delta /= 2; - newPosition = currentPosition + delta; - } - return newPosition; - }, - resetBoundaryX: function() { - this.boundaryX = 0; - }, - resetBoundaryY: function() { - this.boundaryY = 0; - }, - // When user releases the drag, set this.dragging to false, bounce overflow back, and hide scrim. - dragfinish: function(inSender, inEvent) { - if (this.dragging) { - inEvent.preventTap(); - this.dragging = false; - if(!this.isScrolling()) { - this.correctOverflow(); - } - if (this.scrim) { - this.$.scrim.hide(); - } - } - }, - // Bounce back from overscroll region - correctOverflow: function() { - if(this.isInOverScroll()) { - var x = (this.scrollHorizontal) ? this.correctOverflowX() : false; - var y = (this.scrollVertical) ? this.correctOverflowY() : false; - if(x !== false && y !== false) { - this.scrollLeft = (x !== false) ? x : this.getScrollLeft(); - this.scrollTop = (y !== false) ? y : this.getScrollTop(); - this.startOverflowScrolling(); - } else if(x !== false) { - this.scrollLeft = x; - this.scrollTop = this.targetScrollTop || this.scrollTop; - this.targetScrollLeft = this.getScrollLeft(); - if(!this.vertical) { - this.startOverflowScrolling(); - } else { - this.startScrolling(); - } - } else if(y !== false) { - this.scrollTop = y; - this.scrollLeft = this.targetScrollLeft || this.scrollLeft; - this.targetScrollTop = this.getScrollTop(); - if(!this.scrollHorizontal) { - this.startOverflowScrolling(); - } else { - this.startScrolling(); - } - } - } - }, - // Determine if we're overscrolled on the x axis and if so return proper edge value - correctOverflowX: function() { - if(this.isInLeftOverScroll()) { - if(this.beyondBoundary(this.getScrollLeft(), this.leftBoundary, this.boundaryX)) { - return this.leftBoundary; - } - } else if(this.isInRightOverScroll()) { - if(this.beyondBoundary(this.getScrollLeft(), this.rightBoundary, this.boundaryX)) { - return -1*this.rightBoundary; - } - } - return false; - }, - // Determine if we're overscrolled on the y axis and if so return proper edge value - correctOverflowY: function() { - if(this.isInTopOverScroll()) { - if(this.beyondBoundary(this.getScrollTop(), this.topBoundary, this.boundaryY)) { - return this.topBoundary; - } - } else if(this.isInBottomOverScroll()) { - if(this.beyondBoundary(this.getScrollTop(), this.bottomBoundary, this.boundaryY)) { - return -1*this.bottomBoundary; - } - } - return false; - }, - // If we've crossed the determined delta, bounce back - beyondBoundary: function(current,boundary,max) { - return (Math.abs(Math.abs(boundary) - Math.abs(current)) > Math.abs(max)); - }, - // When user flicks/throws scroller, figure the distance to be travelled and whether we will end up - // in the overscroll region. - flick: function(inSender, e) { - if(this.dragging && this.flickOnEnabledAxis(e)) { - this.scrollLeft = this.scrollHorizontal ? this.calculateFlickDistance(this.scrollLeft, -1*e.xVelocity) : this.getScrollLeft(); - this.scrollTop = this.scrollVertical ? this.calculateFlickDistance(this.scrollTop, -1*e.yVelocity) : this.getScrollTop(); - this.targetScrollLeft = this.scrollLeft; - this.targetScrollTop = this.scrollTop; - this.boundaryX = null; - this.boundaryY = null; - // if flick will put the x axis into overscroll, figure where we should bounce back (boundary) - if(this.isInLeftOverScroll()) { - this.boundaryX = this.figureBoundary(this.getScrollLeft()); - } else if(this.isInRightOverScroll()) { - this.boundaryX = this.figureBoundary(-1*this.bottomBoundary - this.getScrollLeft()); - } - // if flick will put the y axis into overscroll, figure where we should bounce back (boundary) - if(this.isInTopOverScroll()) { - this.boundaryY = this.figureBoundary(this.getScrollTop()); - } else if(this.isInBottomOverScroll()) { - this.boundaryY = this.figureBoundary(-1*this.bottomBoundary - this.getScrollTop()); - } - // kickoff scrolling animation - this.startScrolling(); - return this.preventDragPropagation; - } - }, - flickOnEnabledAxis: function(e) { - return Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.scrollHorizontal : this.scrollVertical; - }, - calculateFlickDistance: function(currentPosition, flickVelocity) { - return (currentPosition + (flickVelocity * this.kFlickScalar)); - }, - // Apply the 'scroll' transition, apply new transform based on x and y, and begin - // this.scrollInterval to update the scrollTop/Left values while scrolling - startScrolling: function() { - this.applyTransition("scroll"); - this.effectScroll(); - this.setCSSTransitionInterval(); - this.scrolling = true; - }, - // Apply the 'bounce' transition, apply new transform based on x and y, and begin - // this.scrollInterval to update the scrollTop/Left values while scrolling - startOverflowScrolling: function() { - this.applyTransition("bounce"); - this.effectScroll(); - this.setOverflowTransitionInterval(); - this.scrolling = true; - }, - // Apply the given transition to this.$.client - applyTransition: function(which) { - var transform = this.translation+": "+this.transitions[which]; - this.$.client.applyStyle("-webkit-transition",this.transitions[which]); - }, - // Turn off CSS transition and clear this.scrollInterval - stopScrolling: function() { - this.resetCSSTranslationVals(); - this.clearCSSTransitionInterval(); - this.scrolling = false; - }, - // Create an interval to: update the x/y values while scrolling is happening, check for - // crossing into the overflow region, and bubble a scroll event - setCSSTransitionInterval: function() { - this.clearCSSTransitionInterval(); - this.scrollInterval = setInterval(enyo.bind(this, function() { - this.updateScrollPosition(); - this.correctOverflow(); - }), this.scrollIntervalMS); - }, - // Create an interval to: update the x/y values while scrolling is happening, and bubble - // a scroll event (don't check for crossing into overflow since we're there already) - setOverflowTransitionInterval: function() { - this.clearCSSTransitionInterval(); - this.scrollInterval = setInterval(enyo.bind(this, function() { - this.updateScrollPosition(); - }), this.scrollIntervalMS); - }, - // Save current x/y position and bubble scroll event - updateScrollPosition: function() { - var yChanged = this.updateY(); - var xChanged = this.updateX(); - this.scroll(); - if(!yChanged && !xChanged) { - this.stop(); - } - }, - // Clear this.scrollInterval - clearCSSTransitionInterval: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - } - }, - // Set scroller translation to current position and turn transition off. This effectively - // stops scrolling - resetCSSTranslationVals: function() { - var prop = enyo.dom.getCssTransformProp(); - var transformStyle = window.getComputedStyle(this.$.client.node,null).getPropertyValue(prop).split('(')[1].split(')')[0].split(','); - this.applyTransition("none"); - this.scrollLeft = -1*transformStyle[4]; - this.scrollTop = -1*transformStyle[5]; - this.effectScroll(); - }, - // Figure how far into the overscroll region we should go before bouncing back - figureBoundary: function(target) { - var absTarget = Math.abs(target); - var retVal = absTarget - absTarget/Math.pow(absTarget,0.02); - retVal = target < 0 ? -1*retVal : retVal; - return retVal; - }, - // When transition animation is complete, check if we need to bounce back from overscroll - // region. If not, stop. - transitionComplete: function(inSender, inEvent) { - // Only process transition complete if sent from this container - if(inEvent.originator !== this.$.client) { - return; - } - - var posChanged = false; - - if(this.isInTopOverScroll()) { - posChanged = true; - this.scrollTop = this.topBoundary; - } else if (this.isInBottomOverScroll()) { - posChanged = true; - this.scrollTop = -1*this.bottomBoundary; - } - - if(this.isInLeftOverScroll()) { - posChanged = true; - this.scrollLeft = this.leftBoundary; - } else if (this.isInRightOverScroll()) { - posChanged = true; - this.scrollLeft = -1*this.rightBoundary; - } - - if(posChanged) { - this.startOverflowScrolling(); - } else { - this.stop(); - } - }, - //* Scroll to the specified x and y coordinates - scrollTo: function(inX, inY) { - this.setScrollTop(inY); - this.setScrollLeft(inX); - this.start(); - }, - //* Returns the values of _overleft_ and _overtop_, if any. - getOverScrollBounds: function() { - return { - overleft: Math.min(this.leftBoundary + this.scrollLeft, 0) || Math.max(this.rightBoundary + this.scrollLeft, 0), - overtop: Math.min(this.topBoundary + this.scrollTop, 0) || Math.max(this.bottomBoundary + this.scrollTop, 0) - }; - } -}); diff --git a/enyo/source/touch/TranslateScrollStrategy.js b/enyo/source/touch/TranslateScrollStrategy.js deleted file mode 100644 index 4d08366..0000000 --- a/enyo/source/touch/TranslateScrollStrategy.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - _enyo.TranslateScrollStrategy_ is a helper kind that extends - enyo.TouchScrollStrategy, optimizing - it for scrolling environments in which effecting scroll changes with - transforms is fastest. - - _enyo.TranslateScrollStrategy_ is not typically created in application code. - Instead, it is specified as the value of the `strategyKind` property of an - `enyo.Scroller` or enyo.List, or is used by the - framework implicitly. -*/ -enyo.kind({ - name: "enyo.TranslateScrollStrategy", - kind: "TouchScrollStrategy", - //* Set to true to optimize the strategy to only use translation to scroll; this increases fluidity of - //* scrolling animation. It should not be used when the scroller contains controls that require keyboard - //* input. This is because when _translateOptimized_ is true, it is possible to position inputs such that - //* they will not become visibile when focused. - translateOptimized: false, - //* @protected - components: [ - {name: "clientContainer", classes: "enyo-touch-scroller", components: [ - {name: "client"} - ]} - ], - rendered: function() { - this.inherited(arguments); - enyo.makeBubble(this.$.clientContainer, "scroll"); - }, - getScrollSize: function() { - var n = this.$.client.hasNode(); - return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0}; - }, - create: function() { - this.inherited(arguments); - // apply initial transform so we're always composited - enyo.dom.transformValue(this.$.client, this.translation, "0,0,0"); - }, - calcScrollNode: function() { - return this.$.clientContainer.hasNode(); - }, - maxHeightChanged: function() { - // content should cover scroller at a minimum if there's no max-height. - this.$.client.applyStyle("min-height", this.maxHeight ? null : "100%"); - this.$.client.applyStyle("max-height", this.maxHeight); - this.$.clientContainer.addRemoveClass("enyo-scrollee-fit", !this.maxHeight); - }, - shouldDrag: function(inSender, inEvent) { - // stop and update drag info before checking drag status - this.stop(); - this.calcStartInfo(); - return this.inherited(arguments); - }, - syncScrollMath: function() { - if (!this.translateOptimized) { - this.inherited(arguments); - } - }, - //* @public - //* Sets the left scroll position within the scroller. - setScrollLeft: function(inLeft) { - this.stop(); - if (this.translateOptimized) { - var m = this.$.scrollMath; - m.setScrollX(-inLeft); - m.stabilize(); - } else { - this.inherited(arguments); - } - }, - //* Sets the top scroll position within the scroller. - setScrollTop: function(inTop) { - this.stop(); - if (this.translateOptimized) { - var m = this.$.scrollMath; - m.setScrollY(-inTop); - m.stabilize(); - } else { - this.inherited(arguments); - } - }, - //* Gets the left scroll position within the scroller. - getScrollLeft: function() { - return this.translateOptimized ? this.scrollLeft: this.inherited(arguments); - }, - //* Gets the top scroll position within the scroller. - getScrollTop: function() { - return this.translateOptimized ? this.scrollTop : this.inherited(arguments); - }, - //* @protected - scrollMathStart: function(inSender) { - this.inherited(arguments); - this.scrollStarting = true; - this.startX = 0; - this.startY = 0; - if (!this.translateOptimized && this.scrollNode) { - this.startX = this.getScrollLeft(); - this.startY = this.getScrollTop(); - } - }, - scrollMathScroll: function(inSender) { - if(!this.overscroll) { //don't overscroll past edges - this.scrollLeft = -Math.min(inSender.leftBoundary, Math.max(inSender.rightBoundary, inSender.x)); - this.scrollTop = -Math.min(inSender.topBoundary, Math.max(inSender.bottomBoundary, inSender.y)); - } else { - this.scrollLeft = -inSender.x; - this.scrollTop = -inSender.y; - } - if (this.isScrolling()) { - if (this.$.scrollMath.isScrolling()) { - this.effectScroll(this.startX - this.scrollLeft, this.startY - this.scrollTop); - } - if (this.thumb) { - this.updateThumbs(); - } - } - }, - // While moving, scroller uses translate. - effectScroll: function(inX, inY) { - var o = inX + "px, " + inY + "px" + (this.accel ? ",0" : ""); - enyo.dom.transformValue(this.$.client, this.translation, o); - }, - // When stopped, we use scrollLeft/Top (makes cursor positioning automagic). - effectScrollStop: function() { - if (!this.translateOptimized) { - var t = "0,0" + (this.accel ? ",0" : ""); - // FIXME: normally translate3d changes not effect scrollHeight; however - // there appear to be some dom changes (e.g. showing a node inside the scroller, - // which do cause the scrollHeight to be changed from the translate3d. - // In this case setting the translate3d back to 0 does not restore scrollHeight. - // This causes a problem because setting scrollTop can produced an unexpected result if - // scrollHeight is less than expected. - // We detect this fault by validating scroll bounds and (1) un-apply the translate3d, - // (2) update scrollTop/Left, and (3) re-apply a 0,0,0 translate3d to ensure compositing. - // Luckily this corrects the problem (which appears to be a webkit bug). Note that - // it's important to maintain a composited state (translate3d 0,0,0) or Android 4 is - // slow to start scrolling. - var m = this.$.scrollMath, sb = this._getScrollBounds(); - var needsBoundsFix = Boolean((sb.maxTop + m.bottomBoundary) || (sb.maxLeft + m.rightBoundary)); - enyo.dom.transformValue(this.$.client, this.translation, needsBoundsFix ? null : t); - // note: this asynchronously triggers dom scroll event - this.setScrollLeft(this.scrollLeft); - this.setScrollTop(this.scrollTop); - if (needsBoundsFix) { - enyo.dom.transformValue(this.$.client, this.translation, t); - } - } - }, - // FIXME: we can fix scrolling artifacts BUGS on Android 4.04 with this heinous incantation. - twiddle: function() { - if (this.translateOptimized && this.scrollNode) { // this.scrollNode is not always defined and makes Motorola XOOM crash - this.scrollNode.scrollTop = 1; - this.scrollNode.scrollTop = 0; - } - }, - down: enyo.nop -}); \ No newline at end of file diff --git a/enyo/source/touch/gesture.js b/enyo/source/touch/gesture.js deleted file mode 100644 index 2b42cc5..0000000 --- a/enyo/source/touch/gesture.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - Gesture events: emulates iOS gesture events on non iOS devices - Event Contents - - pageX / pageY: center point between fingers - - rotation: degrees of rotation from beginning of gesture - - scale: % change of distance between fingers -*/ -//* @protected -(function() { - if (!enyo.platform.gesture && enyo.platform.touch) { - enyo.dispatcher.features.push(function(e) { - if (handlers[e.type]) { - touchGestures[e.type](e); - } - }); - } - var handlers = { - touchstart: true, - touchmove: true, - touchend: true - }; - var touchGestures = { - orderedTouches: [], - gesture: null, - touchstart: function(inEvent) { - // some devices can send multiple changed touches on start and end - enyo.forEach(inEvent.changedTouches, function(t) { - var id = t.identifier; - // some devices can send multiple touchstarts - if (enyo.indexOf(id, this.orderedTouches) < 0) { - this.orderedTouches.push(id); - } - }, this); - if (inEvent.touches.length >= 2 && !this.gesture) { - var p = this.gesturePositions(inEvent); - this.gesture = this.gestureVector(p); - this.gesture.angle = this.gestureAngle(p); - this.gesture.scale = 1; - this.gesture.rotation = 0; - var g = this.makeGesture("gesturestart", inEvent, {vector: this.gesture, scale: 1, rotation: 0}); - enyo.dispatch(g); - } - }, - touchend: function(inEvent) { - // some devices can send multiple changed touches on start and end - enyo.forEach(inEvent.changedTouches, function(t) { - enyo.remove(t.identifier, this.orderedTouches); - }, this); - if (inEvent.touches.length <= 1 && this.gesture) { - var t = inEvent.touches[0] || inEvent.changedTouches[inEvent.changedTouches.length - 1]; - // gesture end sends last rotation and scale, with the x/y of the last finger - enyo.dispatch(this.makeGesture("gestureend", inEvent, {vector: {xcenter: t.pageX, ycenter: t.pageY}, scale: this.gesture.scale, rotation: this.gesture.rotation})); - this.gesture = null; - } - }, - touchmove: function(inEvent) { - if (this.gesture) { - var g = this.makeGesture("gesturechange", inEvent); - this.gesture.scale = g.scale; - this.gesture.rotation = g.rotation; - enyo.dispatch(g); - } - }, - findIdentifiedTouch: function(inTouches, inId) { - for (var i = 0, t; (t = inTouches[i]); i++) { - if (t.identifier === inId) { - return t; - } - } - }, - gesturePositions: function(inEvent) { - var first = this.findIdentifiedTouch(inEvent.touches, this.orderedTouches[0]); - var last = this.findIdentifiedTouch(inEvent.touches, this.orderedTouches[this.orderedTouches.length - 1]); - var fx = first.pageX, lx = last.pageX, fy = first.pageY, ly = last.pageY; - // center the first touch as 0,0 - var x = lx - fx, y = ly - fy; - var h = Math.sqrt(x*x + y*y); - return {x: x, y: y, h: h, fx: fx, lx: lx, fy: fy, ly: ly}; - }, - // find rotation angle - gestureAngle: function(inPositions) { - var p = inPositions; - // yay math!, rad -> deg - var a = Math.asin(p.y / p.h) * (180 / Math.PI); - // fix for range limits of asin (-90 to 90) - // Quadrants II and III - if (p.x < 0) { - a = 180 - a; - } - // Quadrant IV - if (p.x > 0 && p.y < 0) { - a += 360; - } - return a; - }, - // find bounding box - gestureVector: function(inPositions) { - // the least recent touch and the most recent touch determine the bounding box of the gesture event - var p = inPositions; - // center the first touch as 0,0 - return { - magnitude: p.h, - xcenter: Math.abs(Math.round(p.fx + (p.x / 2))), - ycenter: Math.abs(Math.round(p.fy + (p.y / 2))) - }; - }, - makeGesture: function(inType, inEvent, inCache) { - var vector, scale, rotation; - if (inCache) { - vector = inCache.vector; - scale = inCache.scale; - rotation = inCache.rotation; - } else { - var p = this.gesturePositions(inEvent); - vector = this.gestureVector(p); - scale = vector.magnitude / this.gesture.magnitude; - // gestureEvent.rotation is difference from the starting angle, clockwise - rotation = (360 + this.gestureAngle(p) - this.gesture.angle) % 360; - } - var e = enyo.clone(inEvent); - return enyo.mixin(e, { - type: inType, - scale: scale, - pageX: vector.xcenter, - pageY: vector.ycenter, - rotation: rotation - }); - } - }; -})(); diff --git a/enyo/source/touch/msevents.js b/enyo/source/touch/msevents.js deleted file mode 100644 index 11ad343..0000000 --- a/enyo/source/touch/msevents.js +++ /dev/null @@ -1,93 +0,0 @@ -//* @protected -(function() { - // add touch-specific gesture feature - var gesture = enyo.gesture; - if (window.navigator.msPointerEnabled) { - var msEvents = [ - "MSPointerDown", - "MSPointerUp", - "MSPointerMove", - "MSPointerOver", - "MSPointerOut", - "MSPointerCancel", - "MSGestureTap", - "MSGestureDoubleTap", - "MSGestureHold", - "MSGestureStart", - "MSGestureChange", - "MSGestureEnd" - ]; - enyo.forEach(msEvents, function(e) { - enyo.dispatcher.listen(document, e); - }); - // add our own MSPointer event handler - enyo.dispatcher.features.push(function(e) { - if (handlers[e.type] && e.isPrimary) { - handlers[e.type](e); - } - }); - // remove the default mouse event handlers - enyo.gesture.events = {}; - } - - var gestureNormalize = function(inType, inEvent) { - var e = enyo.clone(inEvent); - return enyo.mixin(e, { - pageX: inEvent.translationX || 0, - pageY: inEvent.translationY || 0, - // rad -> deg - rotation: (inEvent.rotation * (180 / Math.PI)) || 0, - type: inType, - srcEvent: inEvent, - preventDefault: gesture.preventDefault, - disablePrevention: gesture.disablePrevention - }); - }; - var makeEvent = function(inEvent) { - var e = enyo.clone(inEvent); - e.srcEvent = inEvent; - // normalize "mouse button" info - e.which = 1; - return e; - }; - - var handlers = { - // FIXME: need to register for gestures in MSPointerDown - // according to Microsoft docs - /*MSGestureStart: function(inEvent) { - enyo.dispatch(gestureNormalize("gesturestart", inEvent)); - }, - MSGestureChange: function(inEvent) { - enyo.dispatch(gestureNormalize("gesturechange", inEvent)); - }, - MSGestureEnd: function(inEvent) { - enyo.dispatch(gestureNormalize("gestureend", inEvent)); - },*/ - MSPointerDown: function(inEvent) { - var e = makeEvent(inEvent); - gesture.down(e); - }, - MSPointerUp: function(inEvent) { - var e = makeEvent(inEvent); - gesture.up(e); - }, - MSPointerMove: function(inEvent) { - var e = makeEvent(inEvent); - gesture.move(e); - }, - MSPointerCancel: function(inEvent) { - // FIXME: not really the same as touchend, as touch action - // was cancelled, but Enyo doesn't have that concept - var e = makeEvent(inEvent); - gesture.up(e); - }, - MSPointerOver: function(inEvent) { - var e = makeEvent(inEvent); - gesture.over(e); - }, - MSPointerOut: function(inEvent) { - var e = makeEvent(inEvent); - gesture.out(e); - } - }; -})(); \ No newline at end of file diff --git a/enyo/source/touch/package.js b/enyo/source/touch/package.js deleted file mode 100644 index 814e553..0000000 --- a/enyo/source/touch/package.js +++ /dev/null @@ -1,14 +0,0 @@ -enyo.depends( - "touch.js", - "msevents.js", - "gesture.js", - "ScrollMath.js", - "ScrollStrategy.js", - "Thumb.css", - "Thumb.js", - "TouchScrollStrategy.js", - "TranslateScrollStrategy.js", - "TransitionScrollStrategy.js", - "Scroller.js", - "Scroller.css" -); diff --git a/enyo/source/touch/touch.js b/enyo/source/touch/touch.js deleted file mode 100644 index a628695..0000000 --- a/enyo/source/touch/touch.js +++ /dev/null @@ -1,139 +0,0 @@ -//* @protected -enyo.requiresWindow(function() { - // add touch-specific gesture feature - var gesture = enyo.gesture; - var oldevents = gesture.events; - // - gesture.events.touchstart = function(e) { - // for duration of this touch, only handle touch events. Old event - // structure will be restored during touchend. - gesture.events = touchGesture; - gesture.events.touchstart(e); - }; - // - var touchGesture = { - _touchCount: 0, - touchstart: function(inEvent) { - this._touchCount += inEvent.changedTouches.length; - this.excludedTarget = null; - var e = this.makeEvent(inEvent); - gesture.down(e); - // generate a new event object since over is a different event - e = this.makeEvent(inEvent); - this.overEvent = e; - gesture.over(e); - }, - touchmove: function(inEvent) { - enyo.job.stop("resetGestureEvents"); - // NOTE: allow user to supply a node to exclude from event - // target finding via the drag event. - var de = gesture.drag.dragEvent; - this.excludedTarget = de && de.dragInfo && de.dragInfo.node; - var e = this.makeEvent(inEvent); - gesture.move(e); - // prevent default document scrolling if enyo.bodyIsFitting == true - // avoid window scrolling by preventing default on this event - // note: this event can be made unpreventable (native scrollers do this) - if (enyo.bodyIsFitting) { - inEvent.preventDefault(); - } - // synthesize over and out (normally generated via mouseout) - if (this.overEvent && this.overEvent.target != e.target) { - this.overEvent.relatedTarget = e.target; - e.relatedTarget = this.overEvent.target; - gesture.out(this.overEvent); - gesture.over(e); - } - this.overEvent = e; - }, - touchend: function(inEvent) { - gesture.up(this.makeEvent(inEvent)); - // NOTE: in touch land, there is no distinction between - // a pointer enter/leave and a drag over/out. - // While it may make sense to send a leave event when a touch - // ends, it does not make sense to send a dragout. - // We avoid this by processing out after up, but - // this ordering is ad hoc. - gesture.out(this.overEvent); - // reset the event handlers back to the mouse-friendly ones after - // a short timeout. We can't do this directly in this handler - // because it messes up Android to handle the mouseup event. - // FIXME: for 2.1 release, conditional on platform being - // desktop Chrome, since we're seeing issues in PhoneGap with this - // code. - this._touchCount -= inEvent.changedTouches.length; - }, - // use mouseup after touches are done to reset event handling back to default - // --this works as long as no one did a preventDefault on the touch events - mouseup: function(e) { - if (this._touchCount === 0) { - this.sawMousedown = false; - gesture.events = oldevents; - } - }, - makeEvent: function(inEvent) { - var e = enyo.clone(inEvent.changedTouches[0]); - e.srcEvent = inEvent; - e.target = this.findTarget(e); - // normalize "mouse button" info - e.which = 1; - //enyo.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none")); - return e; - }, - calcNodeOffset: function(inNode) { - if (inNode.getBoundingClientRect) { - var o = inNode.getBoundingClientRect(); - return { - left: o.left, - top: o.top, - width: o.width, - height: o.height - }; - } - }, - findTarget: function(e) { - return document.elementFromPoint(e.clientX, e.clientY); - }, - // NOTE: will find only 1 element under the touch and - // will fail if an element is positioned outside the bounding box of its parent - findTargetTraverse: function(inNode, inX, inY) { - var n = inNode || document.body; - var o = this.calcNodeOffset(n); - if (o && n != this.excludedTarget) { - var x = inX - o.left; - var y = inY - o.top; - //enyo.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")"); - if (x>0 && y>0 && x<=o.width && y<=o.height) { - //enyo.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")"); - var target; - for (var n$=n.childNodes, i=n$.length-1, c; (c=n$[i]); i--) { - target = this.findTargetTraverse(c, inX, inY); - if (target) { - return target; - } - } - return n; - } - } - }, - connect: function() { - enyo.forEach(['ontouchstart', 'ontouchmove', 'ontouchend', 'ongesturestart', 'ongesturechange', 'ongestureend'], function(e) { - document[e] = enyo.dispatch; - }); - if (enyo.platform.androidChrome <= 18 || enyo.platform.silk === 2) { - // HACK: on Chrome for Android v18 on devices with higher density displays, - // document.elementFromPoint expects screen coordinates, not document ones - // bug also appears on Kindle Fire HD - this.findTarget = function(e) { - return document.elementFromPoint(e.screenX, e.screenY); - }; - } else if (!document.elementFromPoint) { - this.findTarget = function(e) { - return this.findTargetTraverse(null, e.clientX, e.clientY); - }; - } - } - }; - // - touchGesture.connect(); -}); \ No newline at end of file diff --git a/enyo/source/ui/Animator.js b/enyo/source/ui/Animator.js deleted file mode 100644 index 5f67121..0000000 --- a/enyo/source/ui/Animator.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - _enyo.Animator_ is a basic animation component. Call _play_ to start the - animation. The animation will run for the period (in milliseconds) specified - by its _duration_ property. The _onStep_ event will fire in quick - succession and should be handled to do something based on the _value_ - property. - - The _value_ property will progress from _startValue_ to _endValue_ during - the animation based on the function referenced by the _easingFunction_ - property. The _stop_ method may be called to manually stop an in-progress - animation; calling it will fire the _onStop_ event. When an animation - completes normally, the _onEnd_ event is fired. - - Event handlers may be specified as functions. If specified, the handler - function will be used to handle the event directly, without sending the - event to its owner or bubbling it. The _context_ property can be used to - call the supplied event functions in a particular "this" context. -*/ -enyo.kind({ - name: "enyo.Animator", - kind: "Component", - published: { - //* Animation duration in milliseconds - duration: 350, - //* Value of _value_ property at the beginning of an animation - startValue: 0, - //* Value of _value_ property at the end of an animation - endValue: 1, - //* Node that must be visible in order for the animation to continue. - //* This reference is destroyed when the animation ceases. - node: null, - //* Function that determines how the animation progresses from - //* _startValue_ to _endValue_ - easingFunction: enyo.easing.cubicOut - }, - events: { - //* Fires when an animation step occurs. - onStep: "", - //* Fires when the animation finishes normally. - onEnd: "", - //* Fires when the animation is prematurely stopped. - onStop: "" - }, - //* @protected - constructed: function() { - this.inherited(arguments); - this._next = enyo.bind(this, "next"); - }, - destroy: function() { - this.stop(); - this.inherited(arguments); - }, - //* @public - //* Plays the animation. - //* For convenience, _inProps_ will be mixed directly into this object. - play: function(inProps) { - this.stop(); - this.reversed = false; - if (inProps) { - enyo.mixin(this, inProps); - } - this.t0 = this.t1 = enyo.now(); - this.value = this.startValue; - this.job = true; - this.next(); - return this; - }, - //* Stops the animation and fires the _onStop_ event. - stop: function() { - if (this.isAnimating()) { - this.cancel(); - this.fire("onStop"); - return this; - } - }, - //* Reverses the direction of a running animation; returns self if animating. - reverse: function() { - if (this.isAnimating()) { - this.reversed = !this.reversed; - var now = this.t1 = enyo.now(); - // adjust start time (t0) to allow for animation done so far to replay - var elapsed = now - this.t0; - this.t0 = now + elapsed - this.duration; - // swap start and end values - var startValue = this.startValue; - this.startValue = this.endValue; - this.endValue = startValue; - return this; - } - }, - //* Returns true if animation is in progress. - isAnimating: function() { - return Boolean(this.job); - }, - //* @protected - requestNext: function() { - this.job = enyo.requestAnimationFrame(this._next, this.node); - }, - cancel: function() { - enyo.cancelRequestAnimationFrame(this.job); - this.node = null; - this.job = null; - }, - shouldEnd: function() { - return (this.dt >= this.duration); - }, - next: function() { - this.t1 = enyo.now(); - this.dt = this.t1 - this.t0; - // time independent - var f = this.fraction = enyo.easedLerp(this.t0, this.duration, this.easingFunction, this.reversed); - this.value = this.startValue + f * (this.endValue - this.startValue); - if (f >= 1 || this.shouldEnd()) { - this.value = this.endValue; - this.fraction = 1; - this.fire("onStep"); - this.fire("onEnd"); - this.cancel(); - } else { - this.fire("onStep"); - this.requestNext(); - } - }, - fire: function(inEventName) { - var fn = this[inEventName]; - if (enyo.isString(fn)) { - this.bubble(inEventName); - } else if (fn) { - fn.call(this.context || window, this); - } - } -}); diff --git a/enyo/source/ui/BaseLayout.js b/enyo/source/ui/BaseLayout.js deleted file mode 100644 index d3eae5f..0000000 --- a/enyo/source/ui/BaseLayout.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - _enyo.BaseLayout_ provides a basic layout strategy, positioning contained - components with the _enyo-positioned_ layoutClass. In addition, it adjusts - the layout when _reflow_ is called, removing or adding the _enyo-fit_ class - for components that have set the _fit_ property. -*/ -enyo.kind({ - name: "enyo.BaseLayout", - kind: enyo.Layout, - layoutClass: "enyo-positioned", - //* Adds or removes the _enyo-fit_ class for components whose _fit_ property - //* has been set. - reflow: function() { - enyo.forEach(this.container.children, function(c) { - if (c.fit !== null) { - c.addRemoveClass("enyo-fit", c.fit); - } - }, this); - } -}); - -//enyo.Control.prototype.layoutKind = "enyo.BaseLayout"; \ No newline at end of file diff --git a/enyo/source/ui/Button.js b/enyo/source/ui/Button.js deleted file mode 100644 index 4de4735..0000000 --- a/enyo/source/ui/Button.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - _enyo.Button_ implements an HTML button, with support for grouping using - enyo.Group. - - For more information, see the documentation on - Buttons in the - Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Button", - //* @protected - kind: enyo.ToolDecorator, - tag: "button", - attributes: { - // set to button, as default is "submit" which can cause unexpected - // problems when controls are used inside a form - type: "button" - }, - //* @public - published: { - //* When true, button is shown as disabled and does not generate tap - //* events - disabled: false - }, - //* @protected - create: function() { - this.inherited(arguments); - this.disabledChanged(); - }, - disabledChanged: function() { - this.setAttribute("disabled", this.disabled); - }, - tap: function() { - if (this.disabled) { - // work around for platforms like Chrome on Android or Opera that send - // mouseup to disabled form controls - return true; - } else { - this.setActive(true); - } - } -}); diff --git a/enyo/source/ui/Checkbox.js b/enyo/source/ui/Checkbox.js deleted file mode 100644 index c9d7e60..0000000 --- a/enyo/source/ui/Checkbox.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - _enyo.Checkbox_ implements an HTML checkbox input, with support for grouping. -*/ -enyo.kind({ - name: "enyo.Checkbox", - kind: enyo.Input, - classes: "enyo-checkbox", - events: { - //* Fires when checkbox is tapped. - onActivate: "" - }, - published: { - //* Value of checkbox; true if checked - checked: false, - //* Group API requirement for determining selected item - active: false, - //* @protected - type: "checkbox" - }, - //* @protected - // disable classes inherited from enyo.Input - kindClasses: "", - handlers: { - onchange: "change", - onclick: "click" - }, - create: function() { - this.inherited(arguments); - }, - rendered: function() { - this.inherited(arguments); - if (this.active) { - this.activeChanged(); - } - this.checkedChanged(); - }, - // instance 'checked' property is linked to DOM 'checked' property - getChecked: function() { - return enyo.isTrue(this.getNodeProperty("checked", this.checked)); - }, - checkedChanged: function() { - this.setNodeProperty("checked", this.checked); - this.setAttribute("checked", this.checked ? "checked" : ""); - this.setActive(this.checked); - }, - // active property, and onActivate event, are part of "GroupItem" interface - // that we support in this object - activeChanged: function() { - this.active = enyo.isTrue(this.active); - this.setChecked(this.active); - this.bubble("onActivate"); - }, - // all input type controls support 'value' property - setValue: function(inValue) { - this.setChecked(enyo.isTrue(inValue)); - }, - getValue: function() { - return this.getChecked(); - }, - valueChanged: function() { - // inherited behavior is to set "value" attribute and node-property - // which does not apply to checkbox (uses "checked") so - // we squelch the inherited method - }, - change: function() { - this.setActive(this.getChecked()); - }, - click: function(inSender, inEvent) { - // Various versions of IE (notably IE8) do not fire 'onchange' for - // checkboxes, so we discern change via 'click'. - // Note: keyboard interaction (e.g. pressing space when focused) fires - // a click event. - if (enyo.platform.ie <= 8) { - this.bubble("onchange", inEvent); - } - } -}); diff --git a/enyo/source/ui/DragAvatar.js b/enyo/source/ui/DragAvatar.js deleted file mode 100644 index ec49233..0000000 --- a/enyo/source/ui/DragAvatar.js +++ /dev/null @@ -1,90 +0,0 @@ -//* @protected -enyo.kind({ - name: "enyo._DragAvatar", - style: "position: absolute; z-index: 10; pointer-events: none; cursor: move;", - showing: false, - showingChanged: function() { - this.inherited(arguments); - document.body.style.cursor = this.showing ? "move" : null; - } -}); - -//* @public -/** - _enyo.DragAvatar_ creates a control to follow the pointer when dragging. It - automatically displays the avatar control when the user drags, and updates - its position relative to the current pointer location. - - enyo.kind({ - name: "App", - handlers: { - ondrag: "drag", - ondragfinish: "dragFinish", - }, - components: [ - {name:"dragAvatar", kind:"DragAvatar", - components: [{tag: "img", src: "images/icon.png"}] - } - ], - drag: function(inSender, inEvent) { - this.$.dragAvatar.drag(inEvent); - }, - dragFinish: function(inSender, inEvent) { - this.$.dragAvatar.hide(); - } - }); -*/ -enyo.kind({ - name: "enyo.DragAvatar", - kind: enyo.Component, - published: { - //* Current visibility state of the DragAvatar - showing: false, - /** - Distance (in pixels) along the horizontal axis between the current - drag position and where the avatar control is displayed. - */ - offsetX: 20, - /** - Distance (in pixels) along the vertical axis between the current - drag position and where the avatar control is displayed. - */ - offsetY: 30 - }, - //* @protected - initComponents: function() { - this.avatarComponents = this.components; - this.components = null; - this.inherited(arguments); - }, - requireAvatar: function() { - // FIXME: there is nobody to call teardownRender on this.avatar - // if document.body.innerHTML has been written over, his node is invalid - // we should have a trap for this condition here - if (!this.avatar) { - this.avatar = this.createComponent({kind: enyo._DragAvatar, parentNode: document.body, showing: false, components: this.avatarComponents}).render(); - } - }, - showingChanged: function() { - this.avatar.setShowing(this.showing); - document.body.style.cursor = this.showing ? "move" : null; - }, - //* @public - /** - Instantiates the avatar control (if necessary), determines correct - position, and calls _show_ to make it visible. - */ - drag: function(inEvent) { - this.requireAvatar(); - this.avatar.setBounds({top: inEvent.pageY - this.offsetY, left: inEvent.pageX + this.offsetX}); - this.show(); - }, - //* Shows the DragAvatar. - show: function() { - this.setShowing(true); - }, - //* Hides the DragAvatar. - hide: function() { - this.setShowing(false); - } -}); diff --git a/enyo/source/ui/FloatingLayer.js b/enyo/source/ui/FloatingLayer.js deleted file mode 100644 index ff78308..0000000 --- a/enyo/source/ui/FloatingLayer.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - _enyo.FloatingLayer_ is a control that provides a layer for controls that - should be displayed above an application. - The FloatingLayer singleton can be set as a control's parent to have the - control float above an application, e.g.: - - create: function() { - this.inherited(arguments); - this.setParent(enyo.floatingLayer); - } - - Note: It's not intended that users create instances of _enyo.FloatingLayer_. -*/ -//* @protected -enyo.kind({ - name: "enyo.FloatingLayer", - //* @protected - create: function() { - this.inherited(arguments); - this.setParent(null); - }, - render: function() { - this.parentNode = document.body; - return this.inherited(arguments); - }, - generateInnerHtml: function() { - return ""; - }, - beforeChildRender: function() { - if (!this.hasNode()) { - this.render(); - } - }, - teardownChildren: function() { - } -}); - -enyo.floatingLayer = new enyo.FloatingLayer(); \ No newline at end of file diff --git a/enyo/source/ui/Group.js b/enyo/source/ui/Group.js deleted file mode 100644 index f9ccd7e..0000000 --- a/enyo/source/ui/Group.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - _enyo.Group_ provides a wrapper around multiple elements. It enables the - creation of radio groups from arbitrary components supporting the - [GroupItem](#enyo.GroupItem) API. -*/ -enyo.kind({ - name: "enyo.Group", - published: { - /** - If true, only one GroupItem in the component list may be active at - a given time. - */ - highlander: true, - //* The control that was last selected - active: null - }, - //* @protected - handlers: { - onActivate: "activate" - }, - activate: function(inSender, inEvent) { - if (this.highlander) { - // deactivation messages are ignored unless it's an attempt - // to deactivate the highlander - if (!inEvent.originator.active) { - // this clause prevents deactivating a grouped item once it's been active. - // the only proper way to deactivate a grouped item is to choose a new - // highlander. - if (inEvent.originator == this.active) { - this.active.setActive(true); - } - } else { - this.setActive(inEvent.originator); - } - } - }, - activeChanged: function(inOld) { - if (inOld) { - inOld.setActive(false); - inOld.removeClass("active"); - } - if (this.active) { - this.active.addClass("active"); - } - } -}); diff --git a/enyo/source/ui/GroupItem.js b/enyo/source/ui/GroupItem.js deleted file mode 100644 index 673ad77..0000000 --- a/enyo/source/ui/GroupItem.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - _enyo.GroupItem_ is the base kind for the Grouping API. It manages the - active state of the component (or the inheriting component). A subkind may - call _setActive_ to set the _active_ property to the desired state; this - will additionally bubble an _onActivate_ event, which can be handled as - needed by the containing components. This is useful for creating groups of - items whose state should be managed as a group. - - For an example of how this works, see the - enyo.Group kind, which enables the creation of - radio groups from arbitrary components that support the Grouping API. -*/ - -enyo.kind({ - name: "enyo.GroupItem", - published: { - //* True if the item is currently selected - active: false - }, - //* @protected - rendered: function() { - this.inherited(arguments); - this.activeChanged(); - }, - activeChanged: function() { - this.bubble("onActivate"); - } -}); diff --git a/enyo/source/ui/Image.js b/enyo/source/ui/Image.js deleted file mode 100644 index 8a72bf0..0000000 --- a/enyo/source/ui/Image.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - _enyo.Image_ implements an HTML <img> element and, optionally, bubbles - the _onload_ and _onerror_ events. Image dragging is suppressed by default, - so as not to interfere with touch interfaces. -*/ -enyo.kind({ - name: "enyo.Image", - //* When true, no _onload_ or _onerror_ event handlers will be created - noEvents: false, - //* @protected - tag: "img", - attributes: { - // note: draggable attribute takes one of these String values: "true", "false", "auto" - // (Boolean _false_ would remove the attribute) - draggable: "false" - }, - create: function() { - if (this.noEvents) { - delete this.attributes.onload; - delete this.attributes.onerror; - } - this.inherited(arguments); - }, - rendered: function() { - this.inherited(arguments); - enyo.makeBubble(this, "load", "error"); - } -}); diff --git a/enyo/source/ui/Input.js b/enyo/source/ui/Input.js deleted file mode 100644 index d13e068..0000000 --- a/enyo/source/ui/Input.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - _enyo.Input_ implements an HTML <input> element with cross-platform - support for change events. - - You can listen for _oninput_ and _onchange_ DOM events from this control - to know when the text inside has been modified. _oninput_ fires immediately, - while _onchange_ fires when the text has changed and the input subsequently - loses focus. - - For more information, see the documentation on - [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.Input", - published: { - /** - Value of the input. Use this property only to initialize the value. - Call _getValue_ and _setValue_ to manipulate the value at runtime. - */ - value: "", - //* Text to display when the input is empty - placeholder: "", - /** - Type of input; if not specified, it's treated as "text". It can - be anything specified for the _type_ attribute in the HTML - specification, including "url", "email", "search", or "number". - */ - type: "", - /** - When true, prevents input into the control. This maps to the - _disabled_ DOM attribute. - */ - disabled: false, - //* When true, select the contents of the input when it gains focus. - selectOnFocus: false - }, - events: { - //* Fires when the input is disabled or enabled. - onDisabledChange: "" - }, - //* Set to true to focus this control when it is rendered - defaultFocus: false, - //* @protected - tag: "input", - classes: "enyo-input", - handlers: { - onfocus: "focused", - oninput: "input", - onclear: "clear", - ondragstart: "dragstart" - }, - create: function() { - if (enyo.platform.ie) { - this.handlers.onkeyup = "iekeyup"; - } - if (enyo.platform.windowsPhone) { - this.handlers.onkeydown = "iekeydown"; - } - this.inherited(arguments); - this.placeholderChanged(); - // prevent overriding a custom attribute with null - if (this.type) { - this.typeChanged(); - } - this.valueChanged(); - }, - rendered: function() { - this.inherited(arguments); - - enyo.makeBubble(this, "focus", "blur"); - - //Force onchange event to be bubbled inside Enyo for IE8 - if(enyo.platform.ie == 8){ - this.setAttribute("onchange", enyo.bubbler); - } - - this.disabledChanged(); - if (this.defaultFocus) { - this.focus(); - } - }, - typeChanged: function() { - this.setAttribute("type", this.type); - }, - placeholderChanged: function() { - this.setAttribute("placeholder", this.placeholder); - }, - disabledChanged: function() { - this.setAttribute("disabled", this.disabled); - this.bubble("onDisabledChange"); - }, - getValue: function() { - return this.getNodeProperty("value", this.value); - }, - valueChanged: function() { - this.setAttribute("value", this.value); - this.setNodeProperty("value", this.value); - }, - iekeyup: function(inSender, inEvent) { - var ie = enyo.platform.ie, kc = inEvent.keyCode; - // input event missing on ie 8, fails to fire on backspace and delete keys in ie 9 - if (ie <= 8 || (ie == 9 && (kc == 8 || kc == 46))) { - this.bubble("oninput", inEvent); - } - }, - iekeydown: function(inSender, inEvent) { - var wp = enyo.platform.windowsPhone, kc = inEvent.keyCode, dt = inEvent.dispatchTarget; - // onchange event fails to fire on enter key for Windows Phone 8, so we force blur - if (wp <= 8 && kc == 13 && this.tag == "input" && dt.hasNode()) { - dt.node.blur(); - } - }, - clear: function() { - this.setValue(""); - }, - focus: function() { - if (this.hasNode()) { - this.node.focus(); - } - }, - //* Returns true if the Input is focused. - hasFocus: function() { - if (this.hasNode()) { - return document.activeElement === this.node; - } - }, - // note: we disallow dragging of an input to allow text selection on all platforms - dragstart: function() { - return this.hasFocus(); - }, - focused: function() { - if (this.selectOnFocus) { - enyo.asyncMethod(this, "selectContents"); - } - }, - selectContents: function() { - var n = this.hasNode(); - - if (n && n.setSelectionRange) { - n.setSelectionRange(0, n.value.length); - } else if (n && n.createTextRange) { - var r = n.createTextRange(); - r.expand("textedit"); - r.select(); - } - } -}); diff --git a/enyo/source/ui/Popup.js b/enyo/source/ui/Popup.js deleted file mode 100644 index 96f06fe..0000000 --- a/enyo/source/ui/Popup.js +++ /dev/null @@ -1,303 +0,0 @@ -/** - _enyo.Popup_ is a control used to display certain content on top of other - content. - - Popups are initially hidden on creation; they can be shown by calling the - _show_ method and re-hidden by calling _hide_. Popups may be centered using - the _centered_ property; if not centered, they should be given a specific - position. - - A popup may be optionally floated above all application content by setting - its _floating_ property to _true_. This has the advantage of guaranteeing - that the popup will be displayed on top of other content. This usage is - appropriate when the popup does not need to scroll along with other content. - - For more information, see the documentation on - [Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer - Guide. - */ -enyo.kind({ - name: "enyo.Popup", - classes: "enyo-popup enyo-no-touch-action", - published: { - //* Set to true to prevent controls outside the popup from receiving - //* events while the popup is showing - modal: false, - //* By default, the popup will hide when the user taps outside it or - //* presses ESC. Set to false to prevent this behavior. - autoDismiss: true, - //* Set to true to render the popup in a floating layer outside of other - //* controls. This can be used to guarantee that the popup will be - //* shown on top of other controls. - floating: false, - //* Set to true to automatically center the popup in the middle of the viewport - centered: false - }, - //* @protected - showing: false, - handlers: { - ondown: "down", - onkeydown: "keydown", - ondragstart: "dragstart", - onfocus: "focus", - onblur: "blur", - onRequestShow: "requestShow", - onRequestHide: "requestHide" - }, - captureEvents: true, - //* @public - events: { - //* Fires after the popup is shown. - onShow: "", - //* Fires after the popup is hidden. - onHide: "" - }, - //* @protected - tools: [ - {kind: "Signals", onKeydown: "keydown"} - ], - create: function() { - this.inherited(arguments); - /*if (this.floating) { - this.setParent(enyo.floatingLayer); - }*/ - this.canGenerate = !this.floating; - }, - render: function() { - if (this.floating) { - if (!enyo.floatingLayer.hasNode()) { - enyo.floatingLayer.render(); - } - this.parentNode = enyo.floatingLayer.hasNode(); - } - this.inherited(arguments); - }, - destroy: function() { - if (this.showing) { - this.release(); - } - this.inherited(arguments); - }, - - reflow: function() { - this.updatePosition(); - this.inherited(arguments); - }, - calcViewportSize: function() { - if (window.innerWidth) { - return { - width: window.innerWidth, - height: window.innerHeight - }; - } else { - var e = document.documentElement; - return { - width: e.offsetWidth, - height: e.offsetHeight - }; - } - }, - updatePosition: function() { - var d = this.calcViewportSize(); - var b = this.getBounds(); - - if (this.targetPosition) { - // For brevity's sake... - var p = this.targetPosition; - - // Test and optionally adjust our target bounds (only first is commented, because logic is effectively identical for all scenarios) - if (typeof p.left === 'number') { - // If popup will be outside window bounds, switch anchor - if (p.left + b.width > d.width) { - if (p.left - b.width >= 0) { - // Switching to right corner will fit in window - p.right = d.width - p.left; - } else { - // Neither corner will work; stick at side of window - p.right = 0; - } - p.left = null; - } else { - p.right = null; - } - } else if (typeof p.right === 'number') { - if (p.right + b.width > d.width) { - if (p.right - b.width >= 0) { - p.left = d.width - p.right; - } else { - p.left = 0; - } - p.right = null; - } else { - p.left = null; - } - } - - if (typeof p.top === 'number') { - if (p.top + b.height > d.height) { - if (p.top - b.height >= 0) { - p.bottom = d.height - p.top; - } else { - p.bottom = 0; - } - p.top = null; - } else { - p.bottom = null; - } - } else if (typeof p.bottom === 'number') { - if (p.bottom + b.height > d.height) { - if (p.bottom - b.height >= 0) { - p.top = d.height - p.bottom; - } else { - p.top = 0; - } - p.bottom = null; - } else { - p.top = null; - } - } - - // 'initial' values are necessary to override positioning rules in the CSS - this.addStyles('left: ' + (p.left !== null ? p.left + 'px' : 'initial') + '; right: ' + (p.right !== null ? p.right + 'px' : 'initial') + '; top: ' + (p.top !== null ? p.top + 'px' : 'initial') + '; bottom: ' + (p.bottom !== null ? p.bottom + 'px' : 'initial') + ';'); - } else if (this.centered) { - this.addStyles( "top: " + Math.max( ( ( d.height - b.height ) / 2 ), 0 ) + "px; left: " + Math.max( ( ( d.width - b.width ) / 2 ), 0 ) + "px;" ); - } - }, - showingChanged: function() { - // auto render when shown. - if (this.floating && this.showing && !this.hasNode()) { - this.render(); - } - // hide while sizing, and move to top corner for accurate sizing - if (this.centered || this.targetPosition) { - this.applyStyle("visibility", "hidden"); - this.addStyles("top: 0px; left: 0px; right: initial; bottom: initial;"); - } - this.inherited(arguments); - if (this.showing) { - this.resized(); - if (this.captureEvents) { - this.capture(); - } - } else { - if (this.captureEvents) { - this.release(); - } - } - // show after sizing - if (this.centered || this.targetPosition) { - this.applyStyle("visibility", null); - } - // events desired due to programmatic show/hide - if (this.hasNode()) { - this[this.showing ? "doShow" : "doHide"](); - } - }, - capture: function() { - enyo.dispatcher.capture(this, !this.modal); - }, - release: function() { - enyo.dispatcher.release(); - }, - down: function(inSender, inEvent) { - //record the down event to verify in tap - this.downEvent = inEvent; - - // prevent focus from shifting outside the popup when modal. - if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) { - inEvent.preventDefault(); - } - }, - tap: function(inSender, inEvent) { - // dismiss on tap if property is set and click started & ended outside the popup - if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this)) && this.downEvent && - (!this.downEvent.dispatchTarget.isDescendantOf(this))) { - this.downEvent = null; - this.hide(); - return true; - } - }, - // if a drag event occurs outside a popup, hide - dragstart: function(inSender, inEvent) { - var inScope = (inEvent.dispatchTarget === this || inEvent.dispatchTarget.isDescendantOf(this)); - if (inSender.autoDismiss && !inScope) { - inSender.setShowing(false); - } - return true; - }, - keydown: function(inSender, inEvent) { - if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) { - this.hide(); - } - }, - // If something inside the popup blurred, keep track of it. - blur: function(inSender, inEvent) { - if (inEvent.dispatchTarget.isDescendantOf(this)) { - this.lastFocus = inEvent.originator; - } - }, - // When something outside the popup focuses (e.g., due to tab key), focus our last focused control. - focus: function(inSender, inEvent) { - var dt = inEvent.dispatchTarget; - if (this.modal && !dt.isDescendantOf(this)) { - if (dt.hasNode()) { - dt.node.blur(); - } - var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode(); - if (n) { - n.focus(); - } - } - }, - requestShow: function(inSender, inEvent) { - this.show(); - return true; - }, - requestHide: function(inSender, inEvent) { - this.hide(); - return true; - }, - - //* @public - /** - Open at the location of a mouse event (_inEvent_). The popup's - position is automatically constrained so that it does not - display outside the viewport, and defaults to anchoring the top - left corner of the popup to the mouse event. - - _inOffset_ is an optional object which may contain left and top - properties to specify an offset relative to the location the - popup would otherwise be positioned. - */ - showAtEvent: function(inEvent, inOffset) { - // Calculate our ideal target based on the event position and offset - var p = { - left: inEvent.centerX || inEvent.clientX || inEvent.pageX, - top: inEvent.centerY || inEvent.clientY || inEvent.pageY - }; - if (inOffset) { - p.left += inOffset.left || 0; - p.top += inOffset.top || 0; - } - - this.showAtPosition(p); - }, - - /** - Open the popup at a specific position. The final location - of the popup will be automatically constrained so that it does not - display outside the viewport. - - _inPosition_ is an object which may contain left, top, bottom, - and right properties to specify where the popup will be anchored. - If both left and right are included, the popup will preference left - (same for top vs. bottom). - */ - showAtPosition: function(inPosition) { - // Save our target position for later processing - this.targetPosition = inPosition; - - // Show the dialog - this.show(); - } -}); diff --git a/enyo/source/ui/Repeater.js b/enyo/source/ui/Repeater.js deleted file mode 100644 index fce6ec2..0000000 --- a/enyo/source/ui/Repeater.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - _enyo.Repeater_ is a simple control for making lists of items. - - The components of a repeater are copied for each item created, and are - wrapped in a control that keeps the state of the item index. - - Example: - - {kind: "Repeater", count: 2, onSetupItem: "setImageSource", components: [ - {kind: "Image"} - ]} - - setImageSource: function(inSender, inEvent) { - var index = inEvent.index; - var item = inEvent.item; - item.$.image.setSrc(this.imageSources[index]); - return true; - } - - Be sure to return _true_ from your _onSetupItem_ handler to avoid having - other event handlers further up the tree try to modify your item control. - - For more information, see the documentation on - [Lists](https://github.com/enyojs/enyo/wiki/Lists) in the Enyo Developer - Guide. -*/ -enyo.kind({ - name: "enyo.Repeater", - published: { - //* Number of items - count: 0 - }, - events: { - /** - Fires when each item is created. - - _inEvent.index_ contains the item's index. - - _inEvent.item_ contains the item control, for decoration. - */ - onSetupItem: "" - }, - create: function() { - this.inherited(arguments); - this.countChanged(); - }, - //* @protected - initComponents: function() { - this.itemComponents = this.components || this.kindComponents; - this.components = this.kindComponents = null; - this.inherited(arguments); - }, - setCount: function(inCount) { - this.setPropertyValue("count", inCount, "countChanged"); - }, - countChanged: function() { - this.build(); - }, - itemAtIndex: function(inIndex) { - return this.controlAtIndex(inIndex); - }, - //* @public - /** Renders the collection of items. This will delete any existing items and - recreate the repeater if called after the repeater has been rendered. - This is called automatically if _setCount_ is called, even if the count - remains the same. - */ - build: function() { - this.destroyClientControls(); - for (var i=0, c; i"); - document.execCommand("insertHTML", false, v); - } - } -}); diff --git a/enyo/source/ui/Select.js b/enyo/source/ui/Select.js deleted file mode 100644 index 4e01311..0000000 --- a/enyo/source/ui/Select.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - _enyo.Select_ implements an HTML selection widget, using - [enyo.Option](#enyo.Option) kinds by default. - - Example: - - {kind: "Select", onchange: "selectChanged", components: [ - {content: "Descending", value: "d"}, - {content: "Ascending", value: "a"} - ]} - - selectChanged: function(inSender, inEvent) { - var s = inSender.getValue(); - if (s == "d") { - this.sortListDescending(); - } else { - this.sortListAscending(); - } - } - - Note: This uses the `, rerender parent instead - // http://support.microsoft.com/default.aspx?scid=kb;en-us;276228 - if (enyo.platform.ie) { - this.parent.render(); - } else { - this.inherited(arguments); - } - }, - //* @public - //* Returns the value of the selected option. - getValue: function() { - if (this.hasNode()) { - return this.node.value; - } - } -}); - -/** - _enyo.Option_ implements the options in an HTML select widget. -*/ -enyo.kind({ - name: "enyo.Option", - published: { - //* Value of the option - value: "" - }, - //* @protected - tag: "option", - create: function() { - this.inherited(arguments); - this.valueChanged(); - }, - valueChanged: function() { - this.setAttribute("value", this.value); - } -}); - -/** - _enyo.OptionGroup_ allows for the grouping of options in a select widget, - and for the disabling of blocks of options. -*/ -enyo.kind({ - name: "enyo.OptionGroup", - published: { - label: "" - }, - //* @protected - tag: "optgroup", - defaultKind: "enyo.Option", - create: function() { - this.inherited(arguments); - this.labelChanged(); - }, - labelChanged: function() { - this.setAttribute("label", this.label); - } -}); diff --git a/enyo/source/ui/Selection.js b/enyo/source/ui/Selection.js deleted file mode 100644 index a0943f0..0000000 --- a/enyo/source/ui/Selection.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - _enyo.Selection_ is used to manage row selection state for lists. It - provides selection state management for both single-select and multi-select - lists. - - // The following is an excerpt from enyo.FlyweightRepeater. - enyo.kind({ - name: "enyo.FlyweightRepeater", - ... - components: [ - {kind: "Selection", onSelect: "selectDeselect", onDeselect: "selectDeselect"}, - ... - ], - tap: function(inSender, inEvent) { - ... - // mark the tapped row as selected - this.$.selection.select(inEvent.index); - ... - }, - selectDeselect: function(inSender, inEvent) { - // this is where a row selection highlight might be applied - this.renderRow(inEvent.key); - } - ... - }) -*/ -enyo.kind({ - name: "enyo.Selection", - kind: enyo.Component, - published: { - //* If true, multiple selections are allowed - multi: false - }, - events: { - /** - Fires when an item is selected. - - {kind: "Selection", onSelect: "selectRow"... - ... - selectRow: function(inSender, inEvent) { - ... - - _inEvent.key_ is whatever key was used to register the selection - (usually a row index). - - _inEvent.data_ references data registered with this key by the code - that made the original selection. - */ - onSelect: "", - /** - Fires when an item is deselected. - - {kind: "Selection", onSelect: "deselectRow"... - ... - deselectRow: function(inSender, inEvent) - ... - - _inEvent.key_ is whatever key was used to request the deselection - (usually a row index). - - _inEvent.data_ references data registered with this key by the code - that made the selection. - */ - onDeselect: "", - //* Fires when selection changes (but not when selection is cleared). - onChange: "" - }, - //* @protected - create: function() { - this.clear(); - this.inherited(arguments); - }, - multiChanged: function() { - if (!this.multi) { - this.clear(); - } - this.doChange(); - }, - highlander: function(inKey) { - if (!this.multi) { - this.deselect(this.lastSelected); - } - }, - //* @public - //* Removes all selections. - clear: function() { - this.selected = {}; - }, - //* Returns true if the _inKey_ row is selected. - isSelected: function(inKey) { - return this.selected[inKey]; - }, - /** - Manually sets a row's state to selected or unselected. - - _inData_ is an optional data object to store in the selection for - that key that will be sent with the _onSelect_ or _onDeselect_ events. - If not used, the data will be set to 'true'. - */ - setByKey: function(inKey, inSelected, inData) { - if (inSelected) { - this.selected[inKey] = (inData || true); - this.lastSelected = inKey; - this.doSelect({key: inKey, data: this.selected[inKey]}); - } else { - var was = this.isSelected(inKey); - delete this.selected[inKey]; - this.doDeselect({key: inKey, data: was}); - } - this.doChange(); - }, - //* Deselects a row. - deselect: function(inKey) { - if (this.isSelected(inKey)) { - this.setByKey(inKey, false); - } - }, - /** - Selects a row. If the _multi_ property is set to false, _select_ will - also deselect the previous selection. - - _inData_ is an optional data object to store in the selection for - that key that will be sent with the _onSelect_ or _onDeselect_ events. - If not used, the data will be set to 'true'. - */ - select: function(inKey, inData) { - if (this.multi) { - this.setByKey(inKey, !this.isSelected(inKey), inData); - } else if (!this.isSelected(inKey)) { - this.highlander(); - this.setByKey(inKey, true, inData); - } - }, - /** - Toggles selection state for a row. If the _multi_ property is set to - false, toggling a selection on will deselect the previous selection. - - _inData_ is an optional data object to store in the selection for - that key that will be sent with the _onSelect_ or _onDeselect_ events. - If not used, the data will be set to 'true'. - */ - toggle: function(inKey, inData) { - if (!this.multi && this.lastSelected != inKey) { - this.deselect(this.lastSelected); - } - this.setByKey(inKey, !this.isSelected(inKey), inData); - }, - /** - Returns the selection as a hash in which each selected item has a value; - unselected items are undefined. - */ - getSelected: function() { - return this.selected; - }, - /** - Remove a row that's included in the selection set. If this row is - selected, it will be unselected. Any rows above this row will - have their keys value reduced by one. - */ - remove: function(inKey) { - var newSelected = {}; - for (var row in this.selected) { - if (row < inKey) { - newSelected[row] = this.selected[row]; - } else if (row > inKey) { - newSelected[row - 1] = this.selected[row]; - } - } - this.selected = newSelected; - } -}); \ No newline at end of file diff --git a/enyo/source/ui/Table.js b/enyo/source/ui/Table.js deleted file mode 100644 index 40f77d9..0000000 --- a/enyo/source/ui/Table.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - TODO: Won't work in IE8 because we can't set innerHTML - on table elements. We'll need to fall back to divs with - table display styles applied. - - Should also facade certain useful table functionality - (specific set TBD). -*/ - -/** - _enyo.Table_ implements an HTML <table> element. - This is a work in progress. -*/ -enyo.kind({ - name: "enyo.Table", - tag: "table", - attributes: {cellpadding: "0", cellspacing: "0"}, - defaultKind: "enyo.TableRow" -}); - -/** - _enyo.TableRow_ implements an HTML <tr> element. -*/ -enyo.kind({ - name: "enyo.TableRow", - tag: "tr", - defaultKind: "enyo.TableCell" -}); - -/** - _enyo.TableCell_ implements an HTML <td> element. -*/ -enyo.kind({ - name: "enyo.TableCell", - tag: "td" -}); \ No newline at end of file diff --git a/enyo/source/ui/TextArea.js b/enyo/source/ui/TextArea.js deleted file mode 100644 index 72e3aaa..0000000 --- a/enyo/source/ui/TextArea.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - _enyo.TextArea_ implements an HTML <textarea> element with - cross-platform support for change events. - - For more information, see the documentation on - [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.TextArea", - kind: enyo.Input, - //* @protected - tag: "textarea", - classes: "enyo-textarea", - // textarea does use value attribute; needs to be kicked when rendered. - rendered: function() { - this.inherited(arguments); - this.valueChanged(); - } -}); diff --git a/enyo/source/ui/ToolDecorator.js b/enyo/source/ui/ToolDecorator.js deleted file mode 100644 index 6ea806a..0000000 --- a/enyo/source/ui/ToolDecorator.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - _enyo.ToolDecorator_ lines up components in a row, centered vertically. -*/ -enyo.kind({ - name: "enyo.ToolDecorator", - //* @protected - kind: enyo.GroupItem, - classes: "enyo-tool-decorator" -}); diff --git a/enyo/source/ui/package.js b/enyo/source/ui/package.js deleted file mode 100644 index d1d78fa..0000000 --- a/enyo/source/ui/package.js +++ /dev/null @@ -1,21 +0,0 @@ -enyo.depends( - "ui.css", - "Animator.js", - "BaseLayout.js", - "Image.js", - "Input.js", - "RichText.js", - "TextArea.js", - "Select.js", - "Group.js", - "GroupItem.js", - "ToolDecorator.js", - "Button.js", - "Checkbox.js", - "Repeater.js", - "DragAvatar.js", - "FloatingLayer.js", - "Popup.js", - "Selection.js", - "Table.js" -); diff --git a/enyo/source/ui/ui.css b/enyo/source/ui/ui.css deleted file mode 100644 index 0c60e9a..0000000 --- a/enyo/source/ui/ui.css +++ /dev/null @@ -1,26 +0,0 @@ -.enyo-inline, .enyo-tool-decorator { - display: inline-block; -} - -.enyo-children-inline > *, .enyo-tool-decorator > * { - display: inline-block; -} - -.enyo-children-middle > *, .enyo-tool-decorator > * { - vertical-align: middle; -} - -.enyo-positioned { - position: relative; -} - -.enyo-fill { - position: relative; - width: 100%; - height: 100%; -} - -.enyo-popup { - position: absolute; - z-index: 10; -} \ No newline at end of file diff --git a/enyo/tools/README.md b/enyo/tools/README.md deleted file mode 100644 index 57c3c56..0000000 --- a/enyo/tools/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Enyo Minifier - -The enyo minifier uses Node.js, [UglifyJS](http://github.com/mishoo/uglifyjs) and the enyo dependency loader to compress any enyo package into a minimized form. - -## Invocation -For convenience, there are both Windows and Unix versions of the script that invokes the node tool. -They follow the same invocation: - - path/to/enyo/tools/minify/minify.sh package.js -output /relative/path/to/build/dir/buildfilename - -An example for lib/onyx, a UI widget set, run from `lib/onyx/minify/minify.sh`, building to `lib/onyx/build` - - ../../../enyo/tools/minify/minify.sh -output ../build/onyx package.js - -The last parameter in the output path, if not ending in a `/`, will be used as the name of the output build files. -The `package.js` file must be in the same directory as the invocation. - -For convenience, packages should include a `minify` folder with both a Windows batch and Unix shell script that runs the minifier. - -## Running tests -1. You first need to install an http server handling php (MANP or WAMP, ...) -2. Configure your http server to serve the files of the enyo project -3. Point your browser to enyo/tools/... to run the various testcases \ No newline at end of file diff --git a/enyo/tools/deploy.js b/enyo/tools/deploy.js deleted file mode 100644 index 5d8d44a..0000000 --- a/enyo/tools/deploy.js +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/env node - -/** -# deploy.js - portable deployment script - -This portable Node.js script minifies both your application, its -libraries & the Enyo framework it is using. The resulting application -is suitable for production usage, either hostet on a web-server or -embedded into a PhoneGap container. - -The script is intended to be run from the application's root directory -(This is unlike previous deprecated incarnations of the scripts -`deploy.sh` and `deploy.bat` that shipped within the `bootplate` -application), where it expects to find a file called `package.js` -(unless the user specifies an alternate location using the `-p` flag). - -This script comes along with Enyo. It automatically uses & embeds the -Enyo version it is shipped with, unless the user specifies another -Enyo version using the `-e enyo_dir` flag. - -When you application has library dependencies (for example -`lib/mylib`), this script uses the `lib/mylib/manifest.json` (if -present) or the old-fashioned deployment scripts `lib/mylib/deploy.sh` -(on Linux & Mac OSX) or `lib/mylib/deploy.bat` (on Windows). -If neither exist, then the entire library is copied (except for .git dir). - -This script also expects to find the following files & folders in the -application root directory. Each of them is copied verbatim in the -output production/deployment folder (the one optionally given using -the `-o` flag). - -* `index.html`, the application startup page -* `icon.png`, the application icon -* `assets/`holds the static application assets, such as images, - videos... etc. - - */ - -// Load dependencies - -var nopt = require("nopt"), - path = require('path'), - fs = require('fs'), - util = require('util'), - shell = require('shelljs'); - -var stat, ppwd, lib, script, scripts = {}; - -// Send message to parent node process, if any -process.on('uncaughtException', function (err) { - var errMsg = err.toString() + err.stack; - console.error(errMsg); - if (process.send) { - // only available if parent process is node - process.send({error: errMsg}); - } - process.exit(1); -}); -// receive error messages from child node processes -process.on('message', function(msg) { - console.dir(basename, msg); - if (msg.error && msg.error.stack) { - console.error(basename, msg.error.stack); - } - if (process.send) { - process.send(msg); - } -}); - -// Parse arguments - -var node = process.argv[0], - deploy = process.argv[1], - sourceDir = process.cwd(), - packageJs = path.resolve(sourceDir, "package.js"), - enyoDir = path.resolve(__dirname, '..'), - buildDir = path.resolve(sourceDir, "build"), - name = path.basename(sourceDir), - outDir = path.resolve(sourceDir, 'deploy', name), - less = true, // LESS compilation, turned on by default - verbose = false; - -function printUsage() { - // format generated using node-optimist... - console.log('\n' + - 'Usage: ' + node + ' ' + deploy + ' [-c][-e enyo_dir][-b build_dir][-o out_dir][-p package_js][-s source_dir]\n' + - '\n' + - 'Options:\n' + - ' -v verbose operation [boolean] [default: ' + verbose + ']\n' + - ' -b alternate build directory [default: "' + buildDir + '"]\n' + - ' -c do not run the LESS compiler [boolean] [default: ' + less + ']\n' + - ' -e location of the enyo framework [default: "' + enyoDir + '"]\n' + - ' -o alternate output directory [default: "' + outDir + '"]\n' + - ' -p location of the main package.js file [default: "' + packageJs + '"]\n' + - ' -s source code root directory [default: "' + sourceDir + '"]\n' + - '\n'); -} - -var opt = nopt(/*knownOpts*/ { - "build": path, - "less": Boolean, - "enyo": path, - "out": path, - "packagejs": path, - "source": path, - "verbose": Boolean, - "help": Boolean -}, /*shortHands*/ { - "b": "--build", - "c": "--no-less", - "e": "--enyo", - "o": "--out", - "p": "--packagejs", - "s": "--source", - "v": "--verbose", - "h": "--help", - "?": "--help" -}, process.argv /*args*/, 2 /*slice*/); - -if (opt.help) { - printUsage(); - process.exit(1); -} - -// nopt has not default values system -buildDir = opt.build || buildDir; -enyoDir = opt.enyo || enyoDir; -outDir = opt.out || outDir; -packageJs = opt.packagejs || - (opt.source ? path.join(opt.source, 'package.js') : undefined) || - packageJs; -sourceDir = opt.source || - (opt.packagejs ? path.dirname(opt.packagejs) : undefined) || - sourceDir; -less = (opt.less !== false) && less; -verbose = opt.verbose; - -var minifier = path.resolve(enyoDir, 'tools', 'minifier', 'minify.js'); -if (verbose) console.log("Using: build_dir=" + buildDir); -if (verbose) console.log("Using: enyo_dir=" + enyoDir); -if (verbose) console.log("Using: out_dir=" + outDir); -if (verbose) console.log("Using: packagejs=" + packageJs); -if (verbose) console.log("Using: source_dir=" + sourceDir); -if (verbose) console.log("Using: less=" + less); - -// utils - -function run(args) { - var command = '"' + args.join('" "') + '"'; - var report; - if (verbose) console.log("Running: '", command, "' from '", process.cwd(), "'"); - report = shell.exec(command, { silent: true }); - if (report.code !== 0) { - throw new Error("Fail: '" + command + "'\n" + report.output); - } -} - -// Prepare target directory - -shell.rm('-rf', path.resolve(outDir)); -shell.rm('-rf', path.resolve(outDir)); -shell.mkdir('-p', path.join(outDir)); - -// Build / Minify - -console.log("Minify-ing Enyo..."); -process.chdir(path.resolve(enyoDir, 'minify')); -run([node, minifier, - '-no-alias', - '-enyo', enyoDir, - // XXX generates $buildDir/enyo.(js|css)' so this is - // XXX rather an 'output_prefix' than an 'out_dir'... - '-output', path.join(buildDir, 'enyo'), - 'package.js']); - -console.log("Minify-ing the application..."); -process.chdir(path.dirname(packageJs)); -run([node, minifier, - '-enyo', enyoDir, - '-output', path.join(buildDir, 'app'), - (less ? '-less' : '-no-less'), - 'package.js']); -process.chdir(sourceDir); - -// Deploy / Copy - -shell.mkdir('-p', path.join(outDir, 'lib')); -shell.cp(path.join(sourceDir, 'index.html'), path.join(sourceDir, 'icon.png'), outDir); -shell.cp('-r', buildDir, outDir); - -var assetsSrcDir = path.join(sourceDir, 'assets'); -if(shell.test('-d', assetsSrcDir)) { - shell.cp('-r', assetsSrcDir, outDir); -} - -var libSrcDir = path.join(sourceDir, 'lib'); -if(shell.test('-d', libSrcDir)) { - shell.ls(libSrcDir).forEach(deployLib); -} - -function deployLib(lib) { - var libOutdir = path.join(outDir, 'lib', lib); - // load & execute sub-'deploy.js' - try { - script = path.join(sourceDir, 'lib', lib, 'deploy.js'); - stat = fs.statSync(script); - if (!stat.isFile()) - throw new Error("*** Not a file: '" + script + "'"); - scripts[lib] = require(script); - scripts[lib].deploy(libOutdir); - } catch(e) { - // backward compatibility: run deploy.sh or deploy.bat - try { - script = path.join(sourceDir, 'lib', lib, 'deploy.' + (process.platform === 'win32' ? 'bat' : 'sh')); - stat = fs.statSync(script); - if (!stat.isFile()) - throw new Error("*** Not a file: '" + script + "'"); - run([script, libOutdir]); - } catch(e2) { - // no deploy.(js|bat|sh): copy everything (then remove ".git", if any) - shell.cp('-r', path.join(sourceDir, 'lib', lib), path.join(outDir, 'lib')); - shell.rm('-rf', path.join(outDir, 'lib', lib, '.git')); - } - } -} - -console.log("Success: the deployable application is available in: ", outDir); -process.exit(0); - - diff --git a/enyo/tools/lessc.bat b/enyo/tools/lessc.bat deleted file mode 100644 index a3b21e0..0000000 --- a/enyo/tools/lessc.bat +++ /dev/null @@ -1,17 +0,0 @@ -REM don't watch the sausage being made -@ECHO OFF - -REM the folder this script is in (*/enyo/tools) -SET TOOLS=%~DP0 - -REM enyo location -SET ENYO=%TOOLS%\.. - -REM lessc script location -SET LESSC=%TOOLS%\minifier\lessc.js - -REM node location -SET NODE=node.exe - -REM use node to invoke lessc with a known path to enyo and imported parameters -%NODE% "%LESSC%" -enyo "%ENYO%" %* diff --git a/enyo/tools/lessc.sh b/enyo/tools/lessc.sh deleted file mode 100644 index 9390758..0000000 --- a/enyo/tools/lessc.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# the folder this script is in (*/enyo/tools) -TOOLS="$(cd `dirname $0`; pwd)" -# enyo location -ENYO="$TOOLS/.." -# lessc script location -LESSC="$TOOLS/minifier/lessc.js" - -# check for node, but quietly -if command -v node >/dev/null 2>&1; then - # use node to invoke minify with a known path to enyo and imported parameters - echo "enyo/tools/lessc.sh args: " $@ - node "$LESSC" -enyo "$ENYO" $@ -else - echo "No node found in path" - exit 1 -fi diff --git a/enyo/tools/minifier/lessc.js b/enyo/tools/minifier/lessc.js deleted file mode 100644 index e329f0a..0000000 --- a/enyo/tools/minifier/lessc.js +++ /dev/null @@ -1,80 +0,0 @@ -var - fs = require("fs"), - path = require("path"), - walker = require("walker"), - jsp = require("uglify-js").parser, - pro = require("uglify-js").uglify, - nopt = require("nopt"), - less = require("less") - ; - -// Shimming path.relative with 0.8.8's version if it doesn't exist -if(!path.relative){ - path.relative = require('./path-relative-shim').relative; -} - -function printUsage() { - w("Enyo Less->CSS Compiler"); - w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)"); - w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory"); - w("-h, -?, -help:", "Show this message"); -} - -function finish(loader) { - for (var i=0, sheet; (sheet=loader.sheets[i]); i++) { - if (sheet.slice(-5) == ".less") { - w(sheet); - var code = fs.readFileSync(sheet, "utf8"); - var parser = new(less.Parser)({filename:sheet, paths:[path.dirname(sheet)]}); - var cssFile = sheet.slice(0,sheet.length-5) + ".css"; - parser.parse(code, function (err, tree) { - if (err) { - console.error(err); - } else { - var css = - "/* WARNING: This is a generated file for backward-compatibility. Most */\n" + - "/* usrs should instead modify LESS files. If you choose to edit this CSS */\n" + - "/* directly rather than LESS files, you should make sure less.xx.yy.min.js */\n" + - "/* is commented out in your debug.html, and run deploy.sh/bat using the */\n" + - "/* '-c' flag to disable LESS compilation. This will force the loader and */\n" + - "/* minifier to fall back to using CSS files in place of the same-name */\n" + - "/* LESS file. */\n" + - "\n" + tree.toCSS() - fs.writeFileSync(cssFile, css, "utf8"); - } - }); - } - } -} - -w = console.log; - -var knownOpts = { - "enyo": String, - "output": String, - "help": Boolean -}; - -var shortHands = { - "enyo": ['--enyo'], - "output": ['--output'], - "h": ['--help'], - "?": ['--help'], - "help": ['--help'] -}; - -opt = nopt(knownOpts, shortHands, process.argv, 2); -opt.source = opt.argv.remain[0]; -//w(opt); -//w(""); - -w(""); - -if (opt.help) { - printUsage(); - process.exit(); -} - -walker.init(opt.enyo); -walker.walk(opt.source, finish); - diff --git a/enyo/tools/minifier/minify.js b/enyo/tools/minifier/minify.js deleted file mode 100644 index dd521db..0000000 --- a/enyo/tools/minifier/minify.js +++ /dev/null @@ -1,231 +0,0 @@ -var - fs = require("fs"), - path = require("path"), - walker = require("walker"), - jsp = require("uglify-js").parser, - pro = require("uglify-js").uglify, - nopt = require("nopt"), - less = require("less") - ; - -var basename = path.basename(__filename), - w = console.log, - e = console.error; - -// Shimming path.relative with 0.8.8's version if it doesn't exist -if(!path.relative){ - path.relative = require('./path-relative-shim').relative; -} - -function printUsage() { - w("Enyo 2.0 Minifier"); - w("Flags:"); - w("-no-less:", "Don't compile less; instad substitute css for less"); - w("-no-alias:", "Don't use path macros"); - w("-alias:", "Give paths a macroized alias"); - w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)"); - w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory"); - w("-h, -?, -help:", "Show this message"); -} - -// properly split path based on platform -function pathSplit(inPath) { - var sep = process.platform == "win32" ? "\\" : "/"; - return inPath.split(sep); -} - -buildPathBlock = function(loader) { - var p$ = []; - for (var i=0, p; (p=loader.packages[i]); i++) { - if (p.name.indexOf("-") == -1) { - p$.push(p.name + ': "' + p.folder + '"'); - } - } - p = p$.join(', '); - return !p ? "" : "\n// minifier: path aliases\n\nenyo.path.addPaths({" + p + "});\n"; -}; - -concatCss = function(loader, doneCB) { - w(""); - var blob = ""; - var addToBlob = function(sheet, code) { - // fix url paths - code = code.replace(/url\([^)]*\)/g, function(inMatch) { - // find the url path, ignore quotes in url string - var matches = /url\s*\(\s*(('([^']*)')|("([^"]*)")|([^'"]*))\s*\)/.exec(inMatch); - var urlPath = matches[3] || matches[5] || matches[6]; - // skip data urls - if (/^data:/.test(urlPath)) { - return "url(" + urlPath + ")"; - } - // skip an external link - if (/^http(:?s)?:/.test(urlPath)) { - return "url(" + urlPath + ")"; - } - // get absolute path to referenced asset - var normalizedUrlPath = path.join(sheet, "..", urlPath); - // Make relative asset path to built css - var relPath = path.relative(path.dirname(opt.output || "build"), normalizedUrlPath); - if (process.platform == "win32") { - relPath = pathSplit(relPath).join("/"); - } - return "url(" + relPath + ")"; - }); - blob += "\n/* " + sheet + " */\n\n" + code + "\n"; - } - // Pops one sheet off the sheets[] array, reads (and parses if less), and then - // recurses again from the async callback until no sheets left, then calls doneCB - var readAndParse = function(sheets) { - var sheet = sheets.shift(); - if (sheet) { - w(sheet); - var isLess = (sheet.slice(-4) == "less"); - if (isLess && (opt.less !== true)) { - sheet = sheet.slice(0, sheet.length-4) + "css"; - isLess = false; - w(" (Substituting CSS: " + sheet + ")"); - } - var code = fs.readFileSync(sheet, "utf8"); - if (isLess) { - var parser = new(less.Parser)({filename:sheet, paths:[path.dirname(sheet)]}); - parser.parse(code, function (err, tree) { - if (err) { - console.error(err); - } else { - addToBlob(sheet, tree.toCSS()); - } - readAndParse(sheets); - }); - } else { - addToBlob(sheet, code); - readAndParse(sheets); - } - } else { - doneCB(blob); - } - } - readAndParse(loader.sheets); -}; - -concatJs = function(loader) { - w(""); - var blob = ""; - for (var i=0, m; (m=loader.modules[i]); i++) { - if (typeof opt.alias === 'undefined' || opt.alias) { - w("* inserting path aliases"); - blob += buildPathBlock(loader); - opt.alias = false; - } - w(m.path); - blob += "\n// " + m.rawPath + "\n\n" + compressJsFile(m.path) + "\n"; - if (opt.alias == m.rawPath) { - w("* inserting path aliases"); - blob += buildPathBlock(loader); - } - } - return blob; -}; - -compress = function(inCode) { - var ast = jsp.parse(inCode); // parse code and get the initial AST - ast = pro.ast_mangle(ast); // get a new AST with mangled names - ast = pro.ast_squeeze(ast); // get an AST with compression optimizations - return pro.gen_code(ast, {indent_level:0, beautify: !opt.aggro, ascii_only:true}); // compressed code here -}; - -compressJsFile = function(inPath) { - var code = fs.readFileSync(inPath, "utf8"); - return compress(code); -}; - -finish = function(loader) { - //w(loader.packages); - //w(''); - // - var output = opt.output || "build"; - var outfolder = path.dirname(output); - var exists = fs.existsSync || path.existsSync; - if (outfolder != "." && !exists(outfolder)) { - fs.mkdirSync(outfolder); - } - // Unfortunately, less parsing is asynchronous, so concatCSS is now as well - concatCss(loader, function(css) { - if (css.length) { - w(""); - fs.writeFileSync(output + ".css", css, "utf8"); - } - // - var js = concatJs(loader); - /* - if (css.length) { - js += "\n// " + "minifier: load css" + "\n\n"; - js += 'enyo.machine.sheet("' + output + '.css");\n'; - } - */ - if (js.length) { - w(""); - fs.writeFileSync(output + ".js", js, "utf8"); - } - // - w(""); - w("done."); - w(""); - - // required to properly terminate a - // node.process.fork() call, as defined by - // - process.exit(0); - }); -}; - -var knownOpts = { - "alias": Boolean, - "enyo": String, - "output": String, - "help": Boolean -}; - -var shortHands = { - "alias": ['--alias'], - "enyo": ['--enyo'], - "output": ['--output'], - "h": ['--help'], - "?": ['--help'], - "help": ['--help'] -}; - -opt = nopt(knownOpts, shortHands, process.argv, 2); -opt.source = opt.argv.remain[0]; -w(opt); -w(""); - -w(""); - -if (opt.help) { - printUsage(); - process.exit(); -} - -// Send message to parent node process, if any -process.on('uncaughtException', function (err) { - e(err.stack); - if (process.send) { - // only available if parent-process is node - process.send({error: err}); - } - process.exit(1); -}); -// receive error messages from child node processes -process.on('message', function(msg) { - console.dir(basename, msg); - if (msg.error && msg.error.stack) { - console.error(basename, msg.error.stack); - } - if (process.send) { - process.send(msg); - } -}); - -walker.init(opt.enyo); -walker.walk(opt.source, finish); - diff --git a/enyo/tools/minifier/node_modules/less/CHANGELOG.md b/enyo/tools/minifier/node_modules/less/CHANGELOG.md deleted file mode 100644 index 1c763f8..0000000 --- a/enyo/tools/minifier/node_modules/less/CHANGELOG.md +++ /dev/null @@ -1,49 +0,0 @@ -# 1.3.0 - -2012-03-10 - -- @media bubbling -- Support arbitrary entities as selectors -- [Variadic argument support](https://gist.github.com/1933613) -- Behaviour of zero-arity mixins has [changed](https://gist.github.com/1933613) -- Allow `@import` directives in any selector -- Media-query features can now be a variable -- Automatic merging of media-query conditions -- Fix global variable leaks -- Fix error message on wrong-arity call -- Fix an `@arguments` behaviour bug -- Fix `::` selector output -- Fix a bug when using @media with mixins - - -# 1.2.1 - -2012-01-15 - -- Fix imports in browser -- Improve error reporting in browser -- Fix Runtime error reports from imported files -- Fix `File not found` import error reporting - - -# 1.2.0 - -2012-01-07 - -- Mixin guards -- New function `percentage` -- New `color` function to parse hex color strings -- New type-checking stylesheet functions -- Fix Rhino support -- Fix bug in string arguments to mixin call -- Fix error reporting when index is 0 -- Fix browser support in WebKit and IE -- Fix string interpolation bug when var is empty -- Support `!important` after mixin calls -- Support vanilla @keyframes directive -- Support variables in certain css selectors, like `nth-child` -- Support @media and @import features properly -- Improve @import support with media features -- Improve error reports from imported files -- Improve function call error reporting -- Improve error-reporting \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/LICENSE b/enyo/tools/minifier/node_modules/less/LICENSE deleted file mode 100644 index 40f3b78..0000000 --- a/enyo/tools/minifier/node_modules/less/LICENSE +++ /dev/null @@ -1,179 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -Copyright (c) 2009-2010 Alexis Sellier diff --git a/enyo/tools/minifier/node_modules/less/Makefile b/enyo/tools/minifier/node_modules/less/Makefile deleted file mode 100644 index b30ad0a..0000000 --- a/enyo/tools/minifier/node_modules/less/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -# -# Run all tests -# -test: - node test/less-test.js - -# -# Run benchmark -# -benchmark: - node benchmark/less-benchmark.js - -# -# Build less.js -# -SRC = lib/less -HEADER = build/header.js -VERSION = `cat package.json | grep version \ - | grep -o '[0-9]\.[0-9]\.[0-9]\+'` -DIST = dist/less-${VERSION}.js -RHINO = dist/less-rhino-${VERSION}.js -DIST_MIN = dist/less-${VERSION}.min.js - -less: - @@mkdir -p dist - @@touch ${DIST} - @@cat ${HEADER} | sed s/@VERSION/${VERSION}/ > ${DIST} - @@echo "(function (window, undefined) {" >> ${DIST} - @@cat build/require.js\ - build/ecma-5.js\ - ${SRC}/parser.js\ - ${SRC}/functions.js\ - ${SRC}/colors.js\ - ${SRC}/tree/*.js\ - ${SRC}/tree.js\ - ${SRC}/browser.js\ - build/amd.js >> ${DIST} - @@echo "})(window);" >> ${DIST} - @@echo ${DIST} built. - -rhino: - @@mkdir -p dist - @@touch ${RHINO} - @@cat build/require-rhino.js\ - build/ecma-5.js\ - ${SRC}/parser.js\ - ${SRC}/functions.js\ - ${SRC}/colors.js\ - ${SRC}/tree/*.js\ - ${SRC}/tree.js\ - ${SRC}/rhino.js > ${RHINO} - @@echo ${RHINO} built. - -min: less - @@echo minifying... - @@uglifyjs ${DIST} > ${DIST_MIN} - @@echo ${DIST_MIN} built. - -server: less - cp dist/less-${VERSION}.js test/html/ - cd test/html && python -m SimpleHTTPServer - -clean: - git rm dist/* - -dist: clean min - git add dist/* - git commit -a -m "(dist) build ${VERSION}" - git archive master --prefix=less/ -o less-${VERSION}.tar.gz - npm publish less-${VERSION}.tar.gz - -stable: - npm tag less ${VERSION} stable - - -.PHONY: test benchmark diff --git a/enyo/tools/minifier/node_modules/less/README.md b/enyo/tools/minifier/node_modules/less/README.md deleted file mode 100644 index 104c56c..0000000 --- a/enyo/tools/minifier/node_modules/less/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Note: The Enyo framework currently uses a [fork of Less](https://github.com/enyojs/less.js) with a minor change to [`lib/less/tree/url.js`](https://github.com/enyojs/less.js/blob/master/lib/less/tree/url.js) to ensure that URL paths are propertly rewritten relative to the file that defines the URL when running the node-based compiler used by Enyo's minifier (this is already the default behavior when compiling via the Less.js browser library). - -The `dist/less-1.3.0e.js` and `dist/less-1.3.0e.min.js` files are the browser library built from the head of the fork with the single url.js change above. - -There is an active conversation happening [here on github](https://github.com/cloudhead/less.js/pull/96) aimed at resolving the inconsistency between the browser and node compilers which the Enyo team is tracking, with the goal of moving back to the less.js master. - -=========== - -less.js -======= - -The **dynamic** stylesheet language. - - - -about ------ - -This is the JavaScript, and now official, stable version of LESS. - -For more information, visit . - -license -------- - -See `LICENSE` file. - -> Copyright (c) 2009-2011 Alexis Sellier diff --git a/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less b/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less deleted file mode 100644 index bf7fef7..0000000 --- a/enyo/tools/minifier/node_modules/less/benchmark/benchmark.less +++ /dev/null @@ -1,3979 +0,0 @@ -@bg: #f01; -@white: #fff; -@grey: #eee; -@black: #000; -@blue: #000; -@accent_colour: #000; -@light_grey: #eee; -@dark_grey: #eee; -@yellow: #422; -@red: #ff0000; -@colour_positive: #ff0000; -@colour_negative: #ff0000; - -.box_shadow (...) { -} -.text_shadow (...) { -} -.border_radius (...) { -} -.border_radius_top_left (...) { -} -.border_radius_top_right (...) { -} -.border_radius_bottom_right (...) { -} -.border_radius_bottom_left (...) { -} -.border_radius_top (...) { -} -.border_radius_right (...) { -} -.border_radius_bottom (...) { -} -.border_radius_left (...) { -} -div.browse { - margin: 0 0 20px; - &.class { - padding: 0; - } - div.header { - padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; - border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; - .border_radius_top(3); color: @light_grey; - h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - .active { - background: @white; color: @black; z-index: 4; - :hover { color: @black; } - } - :hover { color: @white; } - :first-child { .border_radius_left(2); } - :last-child { .border_radius_right(2); margin-right: 0; } - } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - :last-child { - a { border: none; } - } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > ul { - margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; - li { - display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; - background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); - a.remove { - position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; - .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; - img { vertical-align: middle; } - } - div.thumbnail { - .border_radius_top(3); position: relative; z-index: 3; - .marker { - position: absolute; padding: 2px; .border_radius(2); z-index: 3; - background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; - } - .marker.coupon { - height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; - b { - display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; - border-bottom: none; border-right: none; float: left; - } - span { - color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; - padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; - } - } - .marker.video { - position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; - b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } - } - .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } - a.thumbnail { - display: block; overflow: hidden; position: relative; text-align: center; - img { position: relative; display: block; margin: auto; } - } - } - div.text { - margin: 3px 0 0; display: block; - a { text-decoration: none; } - a.title { - display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; - white-space: nowrap; height: 16px; overflow: hidden; - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - small { - font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; - a { font-weight: bold; } - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - } - :hover { - background: @accent_colour; - a.remove { display: block; } - div.thumbnail { - a.marker.remove, a.marker.video { - b { display: inline-block; } - } - a.marker.video { .box_shadow(0, 0, 2, @black); } - } - div.text { - a { color: @white; } - a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - small { - color: @white * 0.75 + @accent_colour * 0.25; - :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - } - } - div.footer a { color: @white; } - } - } - > li.ad div.thumbnail a.thumbnail { - width: 130px; height: 97px; - img { width: 100%; height: 100%; } - } - > li.brand div.thumbnail a.thumbnail { - width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); - img { max-width: 120px; max-height: 87px; } - } - li.paginate { - margin-bottom: 0; - a { - display: block; position: relative; text-decoration: none; height: 131px; - div.arrow { - background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); - height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; - b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } - } - div.label { - position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; - color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; - font-weight: bold; font-size: 12px; text-align: center; - } - :hover { - div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } - } - } - :hover { background: transparent; } - } - li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } - li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } - } - > div.footer { - padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; - border-top: 1px solid @light_grey; .border_radius_bottom(3); - div.info { - float: left; color: @grey; - strong { color: @black; font-weight: normal; } - } - div.pagination { - float: right; - > * { - display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; - .border_radius(3); text-decoration: none; font-weight: bold; - font-size: 10px; text-transform: uppercase; - } - a { color: @grey; } - a:hover { color: @black; } - span.disabled { color: @light_grey; } - span.current { color: @white; background: @bg; border: none; } - span.current:hover { color: @white; } - } - } -} -div.browse.with_categories { margin: 0 0 0 160px; } -div.browse.with_options > ul { .border_radius_top(0); } -div.browse.with_footer > ul { .border_radius_bottom(0); } -/* Browse List */ -div.browse.list { -> ul { - margin: 0; min-height: 320px; - padding: 10px 0 0 10px; overflow: hidden; - > li { - display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; - .border_radius(3); position: relative; line-height: normal; - .marker { - position: absolute; padding: 2px; .border_radius(2); - background: url('/images/transparent_backgrounds/white_75.png'); - img { height: 12px; width: 12px; } - } - img.marker { height: 12px; width: 12px; } - span.marker.new { - color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; - font-weight: bold; - } - a.marker.media_type { - display: inline-block; text-decoration: none; top: 39px; left: 8px; - font-size: 10px; - b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } - img { vertical-align: middle; } - } - a.thumbnail { - float: left; - width: 68px; display: block; overflow: hidden; - border: 1px solid @light_grey; - :hover { border-color: @accent_colour; } - } - span.title_brand { - display: block; margin: 0 0 2px 75px; - a { margin: 0; display: inline; } - a.brand_name { font-weight: normal; font-size: 12px; } - } - a.ad_title { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - a.brand_name { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - small { - display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; - } - small.brand_name { display: inline; margin: 0; } - ul.chart { - margin: 0 0 0 80px; - height: 39px; - } - ul.networks { - margin: 3px 0 0 75px; padding: 0; overflow: hidden; - li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } - } - div.points { - display: none; - font-size: 12px; text-align: right; - label { color: @grey; } - } - a.remove { bottom: -3px; right: -3px; } - } - li.ad { - a.thumbnail { height: 51px; } - span.title_brand { - small.brand_name { - display: block; - } - } - } - li.brand { - a.thumbnail { height: 68px; } - } - } -} -div.browse.list.with_options ul { .border_radius_top(0); } -div.browse.list.with_footer ul { .border_radius_bottom(0); } -div.browse.list.cols_2 { - > ul { - > li { - width: 285px; float: left; - :hover { - background: @white; - } - } - } -} -div.browse.ads.list { - > ul { - > li { - height: 53px; - a.thumbnail { - height: 51px; - } - } - } -} -div.browse.brands.list { - > ul { - > li { - height: 68px; - a.thumbnail { - height: 66px; - } - } - } -} - -/* Categories List */ -#categories { - margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; - ul { - margin: 0; padding: 10px 0 0; - li { - list-style: none; margin: 0; padding: 0; font-size: 14px; - a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } - a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } - } - .all a { font-weight: bold; } - .current a { - background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; - padding-left: 10px; - } - } -} - -/* Ads > Show */ -#ad { - div.header { - overflow: hidden; - h3 { font-size: 16px; margin: 0 0 3px; } - small { - a.category { font-weight: bold; color: @accent_colour; } - span.networks img { position: relative; top: 3px; } - } - span.brand { - float: right; color: @white; - a.brand_name { font-weight: bold; color: @accent_colour; } - } - } - div.content { - padding: 0; position: relative; - a.toggle_size { - display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; - background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; - position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; - } - img.creative { margin: 0 auto; max-width: 540px; display: block; } - object { position: relative; z-index: 44; } - object.video { line-height: 0; font-size: 0; } - object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } - } - div.content.not_video { - padding: 40px; text-align: center; - * { margin-left: auto; margin-right: auto; } - object.flash { margin-bottom: 0; } - } - div.footer { - padding: 0; - div.vote_views { - padding: 5px 10px; overflow: hidden; - div.share { float: right; margin: 2px 0 0 0; } - #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } - } - } -} -#sidebar { - #meta { - table { - margin: 0; - tr:last-child td { padding-bottom: 0; } - td { - padding: 0 0 5px; - ul.networks { - margin: 0; padding: 0; - li { - list-style: none; display: inline; - } - li { - } - } - } - td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } - } - } -} - -/* Voting */ -div.voted { - font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; - img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } -} -#voted_up { - img { background: @colour_positive * 0.66 + @bg * 0.15; } -} -#voted_down { - img { background: @colour_negative * 0.66 + @bg * 0.15; } -} -#encourage_comment { - display: inline-block; line-height: 22px; font-weight: bold; -} -#vote { - overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; - a { - color: @white; font-weight: bold; overflow: hidden; display: block; - width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; - } - a.up { - float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); - :hover { background: @colour_positive * 0.85 + @bg * 0.15; } - } - a.down { - float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); - margin: 0 5px 0 1px; - :hover { background: @colour_negative * 0.85 + @bg * 0.15; } - } -} -#vote.disabled { - a.up { - background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } - a.down { - background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } -} - -/* Panels */ -div.panel { - margin: 0 0 20px; position: relative; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); .border_radius(3); - > div.header { - background: @bg url('/images/panel_header_bg.png') repeat-x top left; border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); - padding: 5px 10px 4px; .border_radius_top(3); min-height: 18px; - h2 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - h3 { color: @white; font-size: 14px; margin: 0; line-height: 18px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - small { display: block; font-size: 12px; color: @light_grey * 0.25 + @white * 0.75; } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - } - a:first-child { .border_radius_left(2); } - a:last-child { .border_radius_right(2); margin-right: 0; } - a.active { background: @white; color: @black; z-index: 4; } - a:hover { color: @white; } - a.active:hover { color: @black; } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - } - li:last-child { - a { border: none; } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > div.content { - background: @white; padding: 10px; - .no_padding { padding: 0; } - } - > div.footer { - background: @light_grey * 0.33 + @white * 0.66; border-top: 1px solid (@light_grey * 0.5 + @white * 0.5); - padding: 4px 10px 5px; .border_radius_bottom(3); - } -} -div.panel.no_footer div.content { .border_radius_bottom(3); } -div.panel.no_header div.content { .border_radius_top(3); } -div.panel.collapsable { - div.header { - cursor: pointer; - b.toggle { float: right; border: 5px solid transparent; border-bottom: 5px solid @white; border-top: none; display: block; width: 0; height: 0; margin: 6px 0 0 0; } - } - div.header:hover { - background-color: @bg * 0.75 + @white * 0.25; - } -} -div.panel.collapsed { - div.header { - border-bottom: none; .border_radius(3); - b.toggle { border-bottom: none; border-top: 5px solid @white; } - } - div.blank { border-bottom: none; .border_radius_bottom(3); } - div.content, div.footer { display: none; } -} - - -/* Sidebar Actions */ -#sidebar { - #actions { - .box_shadow(0, 0, 0, transparent); - div.content { - background: url('/images/transparent_backgrounds/accent_colour_10.png'); text-align: center; - p.endorsement { - margin: 0 0 10px; font-size: 14px; font-weight: bold; - small { font-weight: normal; line-height: inherit; margin: 10px 0 0; } - :last-child { margin: 0; } - } - div.share { margin: 5px 0 0; } - a.button { - font-size: 16px; line-height: normal; height: auto; padding: 5px 10px 5px 35px; font-weight: bold; margin: 0; position: relative; - img { position: absolute; top: 3px; left: 6px; } - } - div.flash.notice { - margin: 10px 0 0; font-size: 22px; - small { font-weight: normal; margin: 0 0 10px; } - } - div.flash.notice.done { margin: 0; } - small { - display: block; margin: 10px 0 0; font-size: 11px; color: #808080; line-height: 12px; - img.favicon { vertical-align: middle; } - } - div.blank { - border: none; background: none; padding: 10px 0 0; border-top: 1px solid (@accent_colour * 0.5 + @white * 0.5); - margin: 10px 0 0; - } - } - } -} - -/* People Lists */ -ul.people { - margin: 0; padding: 10px 0 0 10px; background: @white; - > li { - display: block; margin: 0 10px 10px 0; float: left; padding: 2px; width: 57px; position: relative; - .border_radius(2); background: @white; list-style: none; border: 1px solid (@light_grey * 0.33 + @white * 0.66); - a.avatar { - display: block; width: 59px; height: 59px; overflow: hidden; - img { width: 100%; height: 100%; } - } - a.name { display: block; font-size: 10px; text-align: center; } - :hover { - background: @accent_colour; - a.name { color: @white; } - } - } -} -ul.people.list { - padding: 0; - > li { - margin: 0 0 10px; padding: 0 0 10px; overflow: hidden; float: none; width: auto; .border_radius(0); - border: none; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); - span.points { - float: right; display: block; padding: 5px; background: @light_grey * 0.15 + @white * 0.85; line-height: 1; - text-align: center; width: 50px; height: 30px; .border_radius(3); margin: 0 0 0 10px; - strong { display: block; color: @black; font-size: 16px; margin: 2px 0 0; } - label { color: @grey; text-transform: uppercase; font-size: 10px; } - label.long { display: block; } - label.short { display: none; } - } - a.avatar { float: left; width: 40px; height: 40px; } - a.name { font-size: 14px; font-weight: bold; margin: 0 0 0 50px; text-align: left; } - a.name.long { display: inline; } - a.name.short { display: none; } - span.networks { - display: block; margin: 0 0 0 50px; - img.favicon { vertical-align: middle; } - } - :hover { - background: transparent; - a.name { color: @accent_colour * 0.85 + @black * 0.15; } - } - :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } - } -} -ul.people.list.small { - > li { - span.points { - padding: 3px 6px; height: 18px; font-size: 9px; line-height: 17px; width: 60px; - strong { font-size: 12px; margin: 0; display: inline; } - label { font-size: 9px; } - label.long { display: none; } - label.short { display: inline; } - } - a.avatar { width: 24px; height: 24px; } - a.name { display: inline; line-height: 24px; margin: 0 0 0 5px; font-size: 12px; height: 24px; } - a.name.long { display: none; } - a.name.short { display: inline; } - span.networks { display: inline; margin: 0; } - :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } - } -} -ul.people.tiled { - > li { - width: 28px; padding: 2px; - a.avatar { width: 24px; height: 24px; background: @white; padding: 2px; } - a.name, small, span.networks, span.points { display: none; } - } -} - -/* Comments */ -#comments { - ul { - margin: 0 0 20px; padding: 0; - li { - display: block; list-style: none; padding: 0; margin: 0 0 10px; - span.meta { - margin: 0; overflow: hidden; display: block; - small { font-size: 12px; color: @light_grey; float: right; line-height: 16px; display: inline-block; } - a.avatar { - display: inline-block; height: 16px; width: 16px; position: relative; top: 3px; - img { height: 100%; width: 100%; } - } - a.name { font-weight: bold; line-height: 16px; display: inline-block; } - span.inactive { color: @grey; font-weight: bold; line-height: 16px; display: inline-block; } - } - b.tail { - display: block; width: 0; height: 0; margin: 3px 0 0 10px; border: 5px solid transparent; border-top: none; - border-bottom: 5px solid @white; position: relative; z-index: 2; - } - blockquote { - margin: 0; padding: 10px; .border_radius(3); font-style: normal; background: @white; - color: @dark_grey; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); - } - } - } - form { - margin: 0; - textarea { width: 500px; } - } -} - -/* Sidebar Categories */ -#sidebar { - #categories { - margin: 0 0 20px; - width: auto; - p { margin: 0; } - } -} - -#sidebar { - #ads > ul li, #recommendations > ul li { - width: 81px; - div.thumbnail { - a.thumbnail { height: 60px; width: 81px; } - } - div.text { - a.title { font-size: 11px; height: 14px; line-height: 14px; } - small { display: none; } - } - } - #brands > ul li { - width: 55px; - div.thumbnail { - a.thumbnail { - height: 45px; width: 45px; - img { max-height: 45px; max-width: 45px; } - } - } - div.text { display: none; } - } -} - -/* My Account */ -#accounts_controller { - #top { - #page_title { - #page_options { - a.button.public_profile { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } - } - a.button.goto_dashboard { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } - } - } - } - } - #account_nav { - float: left; width: 200px; margin: 0 20px 0 0; - ul.nav { - margin: 0; padding: 0; - li { - margin: 0 0 5px; display: block; list-style: none; padding: 0; - a { - display: block; height: 30px; text-decoration: none; color: @white; - b { - border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; - height: 0; float: right; display: none; - } - span { - .border_radius(3); background: @bg; display: block; - line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; - } - } - :hover { - a { - color: @white; - b { border-left-color: @bg; display: block; } - span { background: @bg; .border_radius_right(0); } - } - } - } - li.current a { - b { border-left-color: @accent_colour; display: block; } - span { background: @accent_colour; color: @white; .border_radius_right(0); } - } - } - } - #main { - > div { - margin: 0 0 20px; - form { margin: 0; } - } - #profile { - a.avatar { - float: left; display: block; - width: 70px; overflow: hidden; position: relative; text-decoration: none; - img { width: 100%; } - span { - display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; - .border_radius(3); .text_shadow(1, 1, 0, @grey); - text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; - } - } - form { - margin: 0 0 0 90px; - h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } - ul.choices { - li { width: 30%; } - } - div.extra { margin-top: 20px; } - } - } - - #networks { - ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; - li:hover - { - background: @light_grey; display: block; float: left; width: 180px; - padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); - position: relative; - * { line-height: normal; } - img { vertical-align: middle; float: left; } - .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } - small { - font-size: 12px; color: @grey; display: block; margin-left: 42px; - strong { color: @black; font-weight: normal; } - } - :hover { - } - } - li.installed { - background: @white; - border: 2px solid @accent_colour; padding: 8px; - } - li.unavailable { - .name { color: @black; } - :hover { - background: @light_grey; - } - } - li:hover { - background: @light_grey * 0.5 + @white * 0.5; - } - } - } - } -} - -/* Shopping Style Panel */ -#shopping_style { - div.header a.button.small { float: right; } - div.content { - p { - margin: 0 0 10px; - label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } - span { color: @black; } - span.toggle { white-space: nowrap; color: @grey; } - :last-child { margin: 0; } - } - p.more { text-align: left; font-weight: normal; } - p.less { display: none; margin: 0; } - } -} - -/* People Controller */ -#people_controller.index { - #main { - div.panel { - float: left; width: 300px; margin: 0 20px 0 0; - :last-child { margin-right: 0; } - } - } -} -#people_controller.show { - #person_overview, #shopping_style { - a.button.small { - } - } - #content { - #shopping_style { - float: left; width: 240px; margin: 0 20px 0 0; - } - #main { width: 360px; } - } -} - -/* Search Results */ -#search_results { - margin: 0 0 20px; - li { - :hover { - small { color: @white * 0.75 + @accent_colour * 0.25; } - } - } -} -#search { - div.content { - padding: 20px; - form { - margin: 0; float: none; - span.submit_and_options { - display: block; - } - } - p { margin: 0 0 15px; } - h4 { font-weight: normal; margin: 0 0 5px; } - } -} - -/* Recommendations */ -#recommendations { - div.browse { - margin: 0; padding: 0; background: none; - ul { min-height: 0; .border_radius(0); } - } -} - -/* Blank States */ -div.blank { - padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; - border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; - h4 { font-size: 18px; margin: 0 0 10px; } - h4:last-child { margin: 0; } - p { font-size: 16px; margin: 0 0 10px; } - p:last-child { margin: 0; } - p.with_list_number.large { - span { margin-left: 48px; display: block; color: @white; } - } - p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } - a { white-space: nowrap; } - a.hide { - position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); - } -} - -div.blank.small { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 16px; } - p { margin: 0; } -} -div.blank.tiny { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 14px; } - p { margin: 0; font-size: 12px; } -} -div.blank.rounded { - .border_radius(3); margin: 0 0 20px; -} -div.blank.rounded.bottom { .border_radius_top(0); } -div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } -div.blank.no_border_top { border-top: none; } -div.blank.no_border_bottom { border-bottom: none; } -div.blank.no_side_borders { border-right: none; border-left: none; } -div.panel { - div.blank { - padding: 10px 20px; overflow: hidden; margin: 0; - h4 { font-weight: normal; font-size: 14px; } - p, ul { margin: 0 0 10px; font-size: 12px; } - p:last-child, ul:last-child { margin: 0; } - } -} - -/* Sidebar Browse */ -#sidebar { - div.panel { - div.content.browse { - padding: 0; margin: 0; - > ul { - min-height: 0; .border_radius(0); - > li { - div.thumbnail { - a.thumbnail { padding: 5px; } - img.marker.media_type { top: 48px; left: 8px; } - } - div.footer { - a.title, a.name { font-size: 11px; font-weight: normal; } - } - } - } - } - - div.content.browse.ads > ul > li { - width: 93px; - > div.thumbnail a.thumbnail { width: 83px; height: 62px; } - } - div.content.browse.brands { - .border_radius(3); - > ul { - background: none; - > li { - width: 52px; - > div.thumbnail { - padding: 3px; - a.thumbnail { width: 42px; height: 42px; padding: 2px; } - } - li.active { background: @accent_colour; } - } - } - } - div.footer { - div.info { float: none; } - div.pagination { float: none; margin: 3px 0 0; } - } - } -} - -/* List Numbers */ -label.list_number { - float: left; background: url('/images/transparent_backgrounds/black_15.png'); padding: 2px; width: 24px; height: 24px; display: block; - .border_radius(99); - b { - display: block; font-weight: bold; font-size: 14px; color: @white; background: @accent_colour; height: 20px; width: 20px; line-height: 20px; - text-align: center; .border_radius(99); .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); - border: 2px solid @white; - } -} -label.list_number.large { - padding: 4px; width: 48px; height: 48px; .border_radius(99); position: relative; left: -10px; - b { - font-size: 28px; height: 40px; width: 40px; .border_radius(99); line-height: 40px; - .text_shadow(2, 2, 0px, (@accent_colour * 0.75 + @black * 0.25)); border-width: 4px; - } -} - -/* Dashboard */ -#dashboard_controller { - #ads { - span.filter.state { float: right; } - } - #sidebar { - #shopping_style div.content { - p.less { display: block; } - p.more { display: none; } - } - #influences { - div.header { - padding-bottom: 0; - ul.tabs { - position: relative; top: 1px; z-index: 3; - li { - margin: 0 5px 0 0; - a { - border: none; background: url('/images/transparent_backgrounds/white_75.png'); - :hover { color: @black; } - } - } - li.active { - a { - background: @white; border: none; - :hover { color: @black; } - } - } - } - } - - div.tab_content { - overflow: hidden; padding: 0; - > ul { - padding: 10px 10px 0; max-height: 280px; min-height: 120px; overflow-y: scroll; .border_radius_bottom(3px); - } - } - div.footer { - form { - p { - margin: 0 0 5px; - img.marker { float: right; margin: 5px 0 0 0; } - span.invitee { - line-height: 26px; padding: 3px 3px 0; font-size: 14px; - small { color: @grey; font-size: 12px; } - } - } - p.indent { margin-left: 36px; } - p.submit { margin-top: 10px; } - } - } - } - } - - div.panel.full { - > div.content { - margin: 0; padding: 0; background: none; - ul { - li { - width: 148px; - div.thumbnail { - img.marker.media_type { top: 90px; } - a.thumbnail { width: 138px; height: 104px; } - } - } - } - } - } - #people { - form { - padding: 0 0 5px; - input { width: 225px; float: left; margin: 0 5px 0 0; } - a.button { height: 23px; line-height: 23px; width: 60px; padding: 0; text-align: center; } - } - } -} - -/* Remove Pages Titles when Browsing */ -#ads_controller, #brands_controller { - #page_title { display: none; } -} - -/* Brands > Show */ -#brands_controller.show { - #ads { - div.filters { - h3 { font-size: 16px; margin: 0; } - span.show { float: right; } - span.filter.dropdown.localisation { float: right; margin: 0 0 0 10px; } - span.filter.state { float: right; margin: 0 0 0 10px; } - } - } -} - -/* FAQ */ -#pages_controller.faq { - #answers { - h3 { margin-top: 20px; padding-top: 20px; border-top: 1px solid (@light_grey * 0.75 + @white * 0.25); } - h3.first { margin-top: 0; padding-top: 0; border: none; } - } - #questions { - div.content { - padding: 20px; - ul { - margin: 0; padding: 0; - li { - margin: 0 0 10px; list-style: none; display: block; padding: 0; - a { font-size: 14px; } - } - li:last-child { - margin: 0; - } - } - } - } -} - -/* Person Overview */ -#person_overview { - padding: 20px 10px; position: relative; z-index: 25; - #person { - float: left; width: 620px; - a.avatar { - display: block; float: left; width: 60px; height: 60px; - img { height: 100%; width: 100%; } - } - > div { - margin: 0 0 0 75px; color: @white; font-size: 14px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - } - div.name { - h2 { - margin: 0 0 5px; display: inline; - a { - font-size: 20px; font-weight: bold; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - line-height: 1; color: @white; text-decoration: none; - :hover { text-decoration: underline; } - } - a.button.small { - font-size: 10px; - :hover { text-decoration: none; } - } - } - - span.points { - float: right; display: block; padding: 5px 10px; .border_radius(2); text-align: center; background: @white; position: relative; - min-width: 45px; - strong { color: @black; font-weight: bold; font-size: 24px; line-height: 1; display: block; .text_shadow(0, 0, 0, transparent); } - label { font-size: 9px; text-transform: uppercase; color: @grey; display: block; .text_shadow(0, 0, 0, transparent); font-weight: bold; } - } - span.points.with_redeem { - .border_radius_bottom(0); - a.button { - display: block; text-align: center; .border_radius_top(0); font-size: 10px; font-weight: bold; padding: 0; - position: absolute; height: 18px; left: 0; right: 0; bottom: -19px; line-height: 18px; text-transform: uppercase; border: none; - } - } - div.options { margin: 0; } - } - div.meta { - color: @white * 0.66 + @bg * 0.33; - span { color: @white; } - label { color: @white * 0.66 + @bg * 0.33; } - ul.networks { - display: inline; margin: 0; padding: 0; - li { - display: inline; line-height: 1; - img { position: relative; vertical-align: middle; top: -1px; } - } - } - } - - div.extra { - font-size: 12px; margin-top: 20px; margin-bottom: 20px; - span.toggle { - .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - a { font-size: 10px; font-weight: bold; text-transform: uppercase; text-decoration: none; color: @accent_colour; } - b.arrow { display: inline-block; width: 0; height: 0; border: 5px solid transparent; position: relative; top: -2px; } - } - #less_info { - span.toggle { - b.arrow { border-top: 5px solid @accent_colour; border-bottom: 0; } - } - } - #more_info { - span.toggle { - float: right; - b.arrow { border-bottom: 5px solid @accent_colour; border-top: 0; } - } - h4 { - color: @white; margin: 0 0 10px 0; border-bottom: 1px solid (@white * 0.25 + @bg * 0.75); .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - span { font-size: 12px; } - } - p { - margin: 0 0 5px; - label { display: block; float: left; width: 120px; color: @white * 0.66 + @bg * 0.33; } - span { display: block; margin: 0 0 0 130px; } - } - p:last-child { margin: 0; } - - } - } - div.login { - margin: 0 0 0 75px; - a.button { font-weight: bold; } - } - } -} - -/* Dashboard Nav */ -#dashboard_nav { - position: absolute; bottom: 0; left: 10px; margin: 0; padding: 0; overflow: hidden; - li { - display: block; float: left; margin: 0 5px 0 0; - a { - display: block; height: 28px; padding: 0 10px; line-height: 28px; .border_radius_top(2); - text-decoration: none; color: @white; background: url('/images/transparent_backgrounds/accent_colour_30.png'); font-size: 14px; - font-weight: bold; - :hover { background: url('/images/transparent_backgrounds/accent_colour_45.png'); } - } - } - li.active { - a { - background: @white; color: @black; - :hover { color: @black; } - } - } -} - -/* Dwellometer */ -#dwellometer { - z-index: 45; float: right; .box_shadow(0, 0, 0, transparent); margin: 0; - div.content { - text-align: center; position: relative; - object, object embed { position: relative; z-index: 46; line-height: 0; } - div.title { - position: absolute; bottom: 10px; left: 0; right: 0; z-index: 50; - img { width: 120px; display: block; margin: 0 auto; position: relative; left: -5px; } - } - } -} - -/* Activity Stream */ -#activity { - div.content { - ul.events { - padding: 0; margin: 0 0 -10px; - li { - margin: 0; padding: 10px 0; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); - list-style: none; overflow: hidden; - small.meta { - font-size: 12px; color: @light_grey; float: right; - } - a.button { float: right; margin: 0 0 10px 10px; } - a.avatar, a.logo, a.thumbnail { - height: 32px; display: block; float: left; - img { width: 100%; height: 100%; } - } - a.avatar, a.logo, a.icon { width: 32px; } - a.thumbnail { width: 42px; } - div.symbols { - float: left; overflow: hidden; - b { - display: block; float: left; margin: 10px 5px 0; - img { height: 12px; width: 12px; } - } - b.voted { margin: 10px 3px 0; padding: 2px; .border_radius(2); } - b.voted.for { background: @colour_positive * 0.33 + @white * 0.66; } - b.voted.against { background: @colour_negative * 0.33 + @white * 0.66; } - } - /* Temporarily removed avatar and symbol */ -/* div.symbols a.agent, b { display: none; }*/ - div.description { - font-size: 12px; color: @grey; - a.agent { font-weight: bold; } - } - div.comment { - margin-top: 2px; - b.tail { - display: block; margin: 0 0 0 10px; width: 0; height: 0; border: 5px solid transparent; - border-top: none; border-bottom: 5px solid (@light_grey * 0.25 + @white * 0.75); - } - blockquote { - margin: 0; font-style: normal; color: @dark_grey; - .border_radius(3); background: @light_grey * 0.25 + @white * 0.75; padding: 5px 10px; - span.view_comment { - color: @grey; - } - } - } - div.content { - overflow: hidden; - } - } - li.new_comment.ad, li.endorsed.ad, li.voted { - div.description, div.content { margin-left: 106px; } -/* div.description, div.content { margin-left: 53px; }*/ - } - li.new_comment.brand, li.replied_to, li.endorsed.brand, li.connected, li.sn_setup { - div.description, div.content { margin-left: 96px; } -/* div.description, div.content { margin-left: 43px; }*/ - } - li.replied_to { - div.content { - a.thumbnail, a.logo { margin-top: 7px; } - } - } - li.replied_to.ad { - div.content { - div.comment { margin-left: 52px; } - } - } - li.replied_to.brand { - div.content { - div.comment { margin-left: 42px; } - } - } - li.voted div.description span.action { .border_radius(2); color: @dark_grey; padding: 0 3px; white-space: nowrap; } - li.voted.for div.description span.action { background: @colour_positive * 0.15 + @white * 0.85; } - li.voted.against div.description span.action { background: @colour_negative * 0.15 + @white * 0.85; } - li:first-child { padding-top: 0; } - li:last-child { border-bottom: none; } - li:hover div.content div.comment blockquote span.view_comment { - } - } - } -} - -/* Login/Register Modal */ -#login_register { - div.location_select, - div.location_search { margin-left: 130px; } - h3 { - small { font-size: 14px; font-weight: normal; display: block; color: @grey; text-align: left; margin: 0; display: block; } - } -} - -/* Contact Form in Pages */ -#pages_controller { - #sidebar { - #contact { - margin: 15px 0 0; - form { - label { text-align: left; float: none; width: auto; font-size: 12px; font-weight: bold; line-height: 1; margin: 0 0 5px; } - p.submit.indent { - margin: 0; - span.with_cancel { display: none; } - } - } - } - } -} - -/* Exclusive Offers */ -#offers { - div.content { - a.gift { - display: block; text-align: center; - img { height: 100px; } - } - } -} - -div.browse { - margin: 0 0 20px; - &.class { - padding: 0; - } - div.header { - padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; - border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; - .border_radius_top(3); color: @light_grey; - h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - .active { - background: @white; color: @black; z-index: 4; - :hover { color: @black; } - } - :hover { color: @white; } - :first-child { .border_radius_left(2); } - :last-child { .border_radius_right(2); margin-right: 0; } - } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - :last-child { - a { border: none; } - } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > ul { - margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; - li { - display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; - background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); - a.remove { - position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; - .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; - img { vertical-align: middle; } - } - div.thumbnail { - .border_radius_top(3); position: relative; z-index: 3; - .marker { - position: absolute; padding: 2px; .border_radius(2); z-index: 3; - background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; - } - .marker.coupon { - height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; - b { - display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; - border-bottom: none; border-right: none; float: left; - } - span { - color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; - padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; - } - } - .marker.video { - position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; - b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } - } - .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } - a.thumbnail { - display: block; overflow: hidden; position: relative; text-align: center; - img { position: relative; display: block; margin: auto; } - } - } - div.text { - margin: 3px 0 0; display: block; - a { text-decoration: none; } - a.title { - display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; - white-space: nowrap; height: 16px; overflow: hidden; - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - small { - font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; - a { font-weight: bold; } - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - } - :hover { - background: @accent_colour; - a.remove { display: block; } - div.thumbnail { - a.marker.remove, a.marker.video { - b { display: inline-block; } - } - a.marker.video { .box_shadow(0, 0, 2, @black); } - } - div.text { - a { color: @white; } - a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - small { - color: @white * 0.75 + @accent_colour * 0.25; - :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - } - } - div.footer a { color: @white; } - } - } - > li.ad div.thumbnail a.thumbnail { - width: 130px; height: 97px; - img { width: 100%; height: 100%; } - } - > li.brand div.thumbnail a.thumbnail { - width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); - img { max-width: 120px; max-height: 87px; } - } - li.paginate { - margin-bottom: 0; - a { - display: block; position: relative; text-decoration: none; height: 131px; - div.arrow { - background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); - height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; - b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } - } - div.label { - position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; - color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; - font-weight: bold; font-size: 12px; text-align: center; - } - :hover { - div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } - } - } - :hover { background: transparent; } - } - li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } - li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } - } - > div.footer { - padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; - border-top: 1px solid @light_grey; .border_radius_bottom(3); - div.info { - float: left; color: @grey; - strong { color: @black; font-weight: normal; } - } - div.pagination { - float: right; - > * { - display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; - .border_radius(3); text-decoration: none; font-weight: bold; - font-size: 10px; text-transform: uppercase; - } - a { color: @grey; } - a:hover { color: @black; } - span.disabled { color: @light_grey; } - span.current { color: @white; background: @bg; border: none; } - span.current:hover { color: @white; } - } - } -} -div.browse.with_categories { margin: 0 0 0 160px; } -div.browse.with_options > ul { .border_radius_top(0); } -div.browse.with_footer > ul { .border_radius_bottom(0); } -/* Browse List */ -div.browse.list { -> ul { - margin: 0; min-height: 320px; - padding: 10px 0 0 10px; overflow: hidden; - > li { - display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; - .border_radius(3); position: relative; line-height: normal; - .marker { - position: absolute; padding: 2px; .border_radius(2); - background: url('/images/transparent_backgrounds/white_75.png'); - img { height: 12px; width: 12px; } - } - img.marker { height: 12px; width: 12px; } - span.marker.new { - color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; - font-weight: bold; - } - a.marker.media_type { - display: inline-block; text-decoration: none; top: 39px; left: 8px; - font-size: 10px; - b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } - img { vertical-align: middle; } - } - a.thumbnail { - float: left; - width: 68px; display: block; overflow: hidden; - border: 1px solid @light_grey; - :hover { border-color: @accent_colour; } - } - span.title_brand { - display: block; margin: 0 0 2px 75px; - a { margin: 0; display: inline; } - a.brand_name { font-weight: normal; font-size: 12px; } - } - a.ad_title { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - a.brand_name { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - small { - display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; - } - small.brand_name { display: inline; margin: 0; } - ul.chart { - margin: 0 0 0 80px; - height: 39px; - } - ul.networks { - margin: 3px 0 0 75px; padding: 0; overflow: hidden; - li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } - } - div.points { - display: none; - font-size: 12px; text-align: right; - label { color: @grey; } - } - a.remove { bottom: -3px; right: -3px; } - } - li.ad { - a.thumbnail { height: 51px; } - span.title_brand { - small.brand_name { - display: block; - } - } - } - li.brand { - a.thumbnail { height: 68px; } - } - } -} -div.browse.list.with_options ul { .border_radius_top(0); } -div.browse.list.with_footer ul { .border_radius_bottom(0); } -div.browse.list.cols_2 { - > ul { - > li { - width: 285px; float: left; - :hover { - background: @white; - } - } - } -} -div.browse.ads.list { - > ul { - > li { - height: 53px; - a.thumbnail { - height: 51px; - } - } - } -} -div.browse.brands.list { - > ul { - > li { - height: 68px; - a.thumbnail { - height: 66px; - } - } - } -} - -/* Categories List */ -#categories { - margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; - ul { - margin: 0; padding: 10px 0 0; - li { - list-style: none; margin: 0; padding: 0; font-size: 14px; - a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } - a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } - } - .all a { font-weight: bold; } - .current a { - background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; - padding-left: 10px; - } - } -} - -/* Ads > Show */ -#ad { - div.header { - overflow: hidden; - h3 { font-size: 16px; margin: 0 0 3px; } - small { - a.category { font-weight: bold; color: @accent_colour; } - span.networks img { position: relative; top: 3px; } - } - span.brand { - float: right; color: @white; - a.brand_name { font-weight: bold; color: @accent_colour; } - } - } - div.content { - padding: 0; position: relative; - a.toggle_size { - display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; - background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; - position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; - } - img.creative { margin: 0 auto; max-width: 540px; display: block; } - object { position: relative; z-index: 44; } - object.video { line-height: 0; font-size: 0; } - object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } - } - div.content.not_video { - padding: 40px; text-align: center; - * { margin-left: auto; margin-right: auto; } - object.flash { margin-bottom: 0; } - } - div.footer { - padding: 0; - div.vote_views { - padding: 5px 10px; overflow: hidden; - div.share { float: right; margin: 2px 0 0 0; } - #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } - } - } -} -#sidebar { - #meta { - table { - margin: 0; - tr:last-child td { padding-bottom: 0; } - td { - padding: 0 0 5px; - ul.networks { - margin: 0; padding: 0; - li { - list-style: none; display: inline; - } - li { - } - } - } - td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } - } - } -} - -/* Voting */ -div.voted { - font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; - img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } -} -#voted_up { - img { background: @colour_positive * 0.66 + @bg * 0.15; } -} -#voted_down { - img { background: @colour_negative * 0.66 + @bg * 0.15; } -} -#encourage_comment { - display: inline-block; line-height: 22px; font-weight: bold; -} -#vote { - overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; - a { - color: @white; font-weight: bold; overflow: hidden; display: block; - width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; - } - a.up { - float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); - :hover { background: @colour_positive * 0.85 + @bg * 0.15; } - } - a.down { - float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); - margin: 0 5px 0 1px; - :hover { background: @colour_negative * 0.85 + @bg * 0.15; } - } -} -#vote.disabled { - a.up { - background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } - a.down { - background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } -} -#sidebar { - #ads > ul li, #recommendations > ul li { - width: 81px; - div.thumbnail { - a.thumbnail { height: 60px; width: 81px; } - } - div.text { - a.title { font-size: 11px; height: 14px; line-height: 14px; } - small { display: none; } - } - } - #brands > ul li { - width: 55px; - div.thumbnail { - a.thumbnail { - height: 45px; width: 45px; - img { max-height: 45px; max-width: 45px; } - } - } - div.text { display: none; } - } -} - -/* My Account */ -#accounts_controller { - #top { - #page_title { - #page_options { - a.button.public_profile { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } - } - a.button.goto_dashboard { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } - } - } - } - } - #account_nav { - float: left; width: 200px; margin: 0 20px 0 0; - ul.nav { - margin: 0; padding: 0; - li { - margin: 0 0 5px; display: block; list-style: none; padding: 0; - a { - display: block; height: 30px; text-decoration: none; color: @white; - b { - border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; - height: 0; float: right; display: none; - } - span { - .border_radius(3); background: @bg; display: block; - line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; - } - } - :hover { - a { - color: @white; - b { border-left-color: @bg; display: block; } - span { background: @bg; .border_radius_right(0); } - } - } - } - li.current a { - b { border-left-color: @accent_colour; display: block; } - span { background: @accent_colour; color: @white; .border_radius_right(0); } - } - } - } - #main { - > div { - margin: 0 0 20px; - form { margin: 0; } - } - #profile { - a.avatar { - float: left; display: block; - width: 70px; overflow: hidden; position: relative; text-decoration: none; - img { width: 100%; } - span { - display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; - .border_radius(3); .text_shadow(1, 1, 0, @grey); - text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; - } - } - form { - margin: 0 0 0 90px; - h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } - ul.choices { - li { width: 30%; } - } - div.extra { margin-top: 20px; } - } - } - - #networks { - ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; - li:hover - { - background: @light_grey; display: block; float: left; width: 180px; - padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); - position: relative; - * { line-height: normal; } - img { vertical-align: middle; float: left; } - .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } - small { - font-size: 12px; color: @grey; display: block; margin-left: 42px; - strong { color: @black; font-weight: normal; } - } - :hover { - } - } - li.installed { - background: @white; - border: 2px solid @accent_colour; padding: 8px; - } - li.unavailable { - .name { color: @black; } - :hover { - background: @light_grey; - } - } - li:hover { - background: @light_grey * 0.5 + @white * 0.5; - } - } - } - } -} - -/* Shopping Style Panel */ -#shopping_style { - div.header a.button.small { float: right; } - div.content { - p { - margin: 0 0 10px; - label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } - span { color: @black; } - span.toggle { white-space: nowrap; color: @grey; } - :last-child { margin: 0; } - } - p.more { text-align: left; font-weight: normal; } - p.less { display: none; margin: 0; } - } -} - -/* People Controller */ -#people_controller.index { - #main { - div.panel { - float: left; width: 300px; margin: 0 20px 0 0; - :last-child { margin-right: 0; } - } - } -} -#people_controller.show { - #person_overview, #shopping_style { - a.button.small { - } - } - #content { - #shopping_style { - float: left; width: 240px; margin: 0 20px 0 0; - } - #main { width: 360px; } - } -} - -/* Search Results */ -#search_results { - margin: 0 0 20px; - li { - :hover { - small { color: @white * 0.75 + @accent_colour * 0.25; } - } - } -} -#search { - div.content { - padding: 20px; - form { - margin: 0; float: none; - span.submit_and_options { - display: block; - } - } - p { margin: 0 0 15px; } - h4 { font-weight: normal; margin: 0 0 5px; } - } -} - -/* Recommendations */ -#recommendations { - div.browse { - margin: 0; padding: 0; background: none; - ul { min-height: 0; .border_radius(0); } - } -} - -/* Blank States */ -div.blank { - padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; - border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; - h4 { font-size: 18px; margin: 0 0 10px; } - h4:last-child { margin: 0; } - p { font-size: 16px; margin: 0 0 10px; } - p:last-child { margin: 0; } - p.with_list_number.large { - span { margin-left: 48px; display: block; color: @white; } - } - p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } - a { white-space: nowrap; } - a.hide { - position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); - } -} - -div.blank.small { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 16px; } - p { margin: 0; } -} -div.blank.tiny { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 14px; } - p { margin: 0; font-size: 12px; } -} -div.blank.rounded { - .border_radius(3); margin: 0 0 20px; -} -div.blank.rounded.bottom { .border_radius_top(0); } -div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } -div.blank.no_border_top { border-top: none; } -div.blank.no_border_bottom { border-bottom: none; } -div.blank.no_side_borders { border-right: none; border-left: none; } -div.panel { - div.blank { - padding: 10px 20px; overflow: hidden; margin: 0; - h4 { font-weight: normal; font-size: 14px; } - p, ul { margin: 0 0 10px; font-size: 12px; } - p:last-child, ul:last-child { margin: 0; } - } -} - -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -}h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; -} -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - font-family: @a, @a, @a; -} - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -}h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; -} -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - font-family: @a, @a, @a; -} - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} diff --git a/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js b/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js deleted file mode 100644 index 68fe1ad..0000000 --- a/enyo/tools/minifier/node_modules/less/benchmark/less-benchmark.js +++ /dev/null @@ -1,47 +0,0 @@ -var path = require('path'), - fs = require('fs'), - sys = require('util'); - -var less = require('../lib/less'); -var file = path.join(__dirname, 'benchmark.less'); - -if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) } - -fs.readFile(file, 'utf8', function (e, data) { - var tree, css, start, end, total; - - sys.puts("Benchmarking...\n", path.basename(file) + " (" + - parseInt(data.length / 1024) + " KB)", ""); - - start = new(Date); - - new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) { - end = new(Date); - - total = end - start; - - sys.puts("Parsing: " + - total + " ms (" + - parseInt(1000 / total * - data.length / 1024) + " KB\/s)"); - - start = new(Date); - css = tree.toCSS(); - end = new(Date); - - sys.puts("Generation: " + (end - start) + " ms (" + - parseInt(1000 / (end - start) * - data.length / 1024) + " KB\/s)"); - - total += end - start; - - sys.puts("Total: " + total + "ms (" + - parseInt(1000 / total * data.length / 1024) + " KB/s)"); - - if (err) { - less.writeError(err); - process.exit(3); - } - }); -}); - diff --git a/enyo/tools/minifier/node_modules/less/bin/lessc b/enyo/tools/minifier/node_modules/less/bin/lessc deleted file mode 100644 index 690535f..0000000 --- a/enyo/tools/minifier/node_modules/less/bin/lessc +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env node - -var path = require('path'), - fs = require('fs'), - sys = require('util'), - os = require('os'); - -var less = require('../lib/less'); -var args = process.argv.slice(1); -var options = { - compress: false, - yuicompress: false, - optimization: 1, - silent: false, - paths: [], - color: true, - strictImports: false -}; -var continueProcessing = true, - currentErrorcode; - -// calling process.exit does not flush stdout always -// so use this to set the exit code -process.on('exit', function() { process.reallyExit(currentErrorcode) }); - -args = args.filter(function (arg) { - var match; - - if (match = arg.match(/^-I(.+)$/)) { - options.paths.push(match[1]); - return false; - } - - if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] } - else { return arg } - - switch (arg) { - case 'v': - case 'version': - sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); - continueProcessing = false; - case 'verbose': - options.verbose = true; - break; - case 's': - case 'silent': - options.silent = true; - break; - case 'strict-imports': - options.strictImports = true; - break; - case 'h': - case 'help': - require('../lib/less/lessc_helper').printUsage(); - continueProcessing = false; - case 'x': - case 'compress': - options.compress = true; - break; - case 'yui-compress': - options.yuicompress = true; - break; - case 'no-color': - options.color = false; - break; - case 'include-path': - options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') - .map(function(p) { - if (p) { - return path.resolve(process.cwd(), p); - } - }); - break; - case 'O0': options.optimization = 0; break; - case 'O1': options.optimization = 1; break; - case 'O2': options.optimization = 2; break; - case 'line-numbers': - options.dumpLineNumbers = match[2]; - break; - } -}); - -if (!continueProcessing) { - return; -} - -var input = args[1]; -if (input && input != '-') { - input = path.resolve(process.cwd(), input); -} -var output = args[2]; -if (output) { - output = path.resolve(process.cwd(), output); -} - -if (! input) { - sys.puts("lessc: no input files"); - sys.puts(""); - require('../lib/less/lessc_helper').printUsage(); - currentErrorcode = 1; - return; -} - -var css, fd, tree; - -var parseLessFile = function (e, data) { - if (e) { - sys.puts("lessc: " + e.message); - currentErrorcode = 1; - return; - } - - new(less.Parser)({ - paths: [path.dirname(input)].concat(options.paths), - optimization: options.optimization, - filename: input, - strictImports: options.strictImports, - dumpLineNumbers: options.dumpLineNumbers - }).parse(data, function (err, tree) { - if (err) { - less.writeError(err, options); - currentErrorcode = 1; - return; - } else { - try { - css = tree.toCSS({ - compress: options.compress, - yuicompress: options.yuicompress - }); - if (output) { - fd = fs.openSync(output, "w"); - fs.writeSync(fd, css, 0, "utf8"); - fs.closeSync(fd); - } else { - sys.print(css); - } - } catch (e) { - less.writeError(e, options); - currentErrorcode = 2; - return; - } - } - }); -}; - -if (input != '-') { - fs.readFile(input, 'utf-8', parseLessFile); -} else { - process.stdin.resume(); - process.stdin.setEncoding('utf8'); - - var buffer = ''; - process.stdin.on('data', function(data) { - buffer += data; - }); - - process.stdin.on('end', function() { - parseLessFile(false, buffer); - }); -} diff --git a/enyo/tools/minifier/node_modules/less/build/amd.js b/enyo/tools/minifier/node_modules/less/build/amd.js deleted file mode 100644 index c4b1187..0000000 --- a/enyo/tools/minifier/node_modules/less/build/amd.js +++ /dev/null @@ -1,6 +0,0 @@ -// amd.js -// -// Define Less as an AMD module. -if (typeof define === "function" && define.amd) { - define("less", [], function () { return less; } ); -} diff --git a/enyo/tools/minifier/node_modules/less/build/ecma-5.js b/enyo/tools/minifier/node_modules/less/build/ecma-5.js deleted file mode 100644 index 420bd88..0000000 --- a/enyo/tools/minifier/node_modules/less/build/ecma-5.js +++ /dev/null @@ -1,120 +0,0 @@ - -// ecma-5.js -// -// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License -// -- tlrobinson Tom Robinson -// dantman Daniel Friesen - -// -// Array -// -if (!Array.isArray) { - Array.isArray = function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" || - (obj instanceof Array); - }; -} -if (!Array.prototype.forEach) { - Array.prototype.forEach = function(block, thisObject) { - var len = this.length >>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} diff --git a/enyo/tools/minifier/node_modules/less/build/header.js b/enyo/tools/minifier/node_modules/less/build/header.js deleted file mode 100644 index c491d92..0000000 --- a/enyo/tools/minifier/node_modules/less/build/header.js +++ /dev/null @@ -1,7 +0,0 @@ -// -// LESS - Leaner CSS v@VERSION -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// diff --git a/enyo/tools/minifier/node_modules/less/build/require-rhino.js b/enyo/tools/minifier/node_modules/less/build/require-rhino.js deleted file mode 100644 index 02bc83c..0000000 --- a/enyo/tools/minifier/node_modules/less/build/require-rhino.js +++ /dev/null @@ -1,7 +0,0 @@ -// -// Stub out `require` in rhino -// -function require(arg) { - return less[arg.split('/')[1]]; -}; - diff --git a/enyo/tools/minifier/node_modules/less/build/require.js b/enyo/tools/minifier/node_modules/less/build/require.js deleted file mode 100644 index 4d5b172..0000000 --- a/enyo/tools/minifier/node_modules/less/build/require.js +++ /dev/null @@ -1,7 +0,0 @@ -// -// Stub out `require` in the browser -// -function require(arg) { - return window.less[arg.split('/')[1]]; -}; - diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js deleted file mode 100644 index 487c06a..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.js +++ /dev/null @@ -1,2695 +0,0 @@ -// -// LESS - Leaner CSS v1.1.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function (window, undefined) { -// -// Stub out `require` in the browser -// -function require(arg) { - return window.less[arg.split('/')[1]]; -}; - - -// ecma-5.js -// -// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License -// -- tlrobinson Tom Robinson -// dantman Daniel Friesen - -// -// Array -// -if (!Array.isArray) { - Array.isArray = function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" || - (obj instanceof Array); - }; -} -if (!Array.prototype.forEach) { - Array.prototype.forEach = function(block, thisObject) { - var len = this.length >>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - less = exports, - tree = require('less/tree'); -} else { - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '&' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page|@-[-a-z]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args) { - this.name = name; - this.args = args; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - return tree.functions[this.name].apply(tree.functions, args); - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value.trim(); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else { - return this.value[0].eval(env); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - toCSS: function () { - if (this.escaped) { - return this.evaluated; - } else { - return JSON.stringify(this.evaluated); - } - }, - eval: function (env) { - var result, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return new(tree.Variable)('@' + name).eval(env).value; - }); - - expression = new(Function)('return (' + expression + ')'); - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - this.evaluated = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - return this; - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(this.arguments, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - this.value = this.value.replace(/@\{([\w-]+)\}/g, function (_, name) { - return new(tree.Variable)('@' + name).eval(env).value; - }).replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, this.index, true).eval(env).toCSS(); - }); - return this; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - for (var s = 0; s < this.selectors.length; s++) { - for (var c = 0; c < context.length; c++) { - paths.push(context[c].concat([this.selectors[s]])); - } - } - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - styles[i].type = 'text/css'; - styles[i].innerHTML = tree.toCSS(); - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js deleted file mode 100644 index ede454e..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.0.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// -// LESS - Leaner CSS v1.1.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -// -// LESS - Leaner CSS v1.1.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value[0].eval(b)},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - less = exports, - tree = require('less/tree'); -} else { - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '&' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page|@-[-a-z]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args) { - this.name = name; - this.args = args; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - return tree.functions[this.name].apply(tree.functions, args); - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value.trim(); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(this.arguments, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - this.value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - return new(tree.Variable)('@' + name, that.index).eval(env).value; - }); - return this; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - for (var s = 0; s < this.selectors.length; s++) { - for (var c = 0; c < context.length; c++) { - paths.push(context[c].concat([this.selectors[s]])); - } - } - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('less/tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - styles[i].type = 'text/css'; - styles[i].innerHTML = tree.toCSS(); - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js deleted file mode 100644 index c204123..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.1.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// -// LESS - Leaner CSS v1.1.1 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -// -// LESS - Leaner CSS v1.1.1 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree" -)),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - less = exports, - tree = require('less/tree'); -} else { - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '&' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page|@-[-a-z]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args) { - this.name = name; - this.args = args; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - return tree.functions[this.name].apply(tree.functions, args); - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value.trim(); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - for (var s = 0; s < this.selectors.length; s++) { - for (var c = 0; c < context.length; c++) { - paths.push(context[c].concat([this.selectors[s]])); - } - } - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('less/tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - styles[i].type = 'text/css'; - styles[i].innerHTML = tree.toCSS(); - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js deleted file mode 100644 index 9b2fc8a..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.2.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// -// LESS - Leaner CSS v1.1.2 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -// -// LESS - Leaner CSS v1.1.2 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){ -if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - less = exports, - tree = require('less/tree'); -} else { - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '&' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page|@-[-a-z]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value.trim(); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - for (var s = 0; s < this.selectors.length; s++) { - for (var c = 0; c < context.length; c++) { - paths.push(context[c].concat([this.selectors[s]])); - } - } - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('less/tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - styles[i].type = 'text/css'; - styles[i].innerHTML = tree.toCSS(); - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js deleted file mode 100644 index 6e4d5cf..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.3.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// -// LESS - Leaner CSS v1.1.3 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -// -// LESS - Leaner CSS v1.1.3 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this -.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - less = exports, - tree = require('less/tree'); -} else { - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^(?:\d*\.)?\d+%/); - - if (e) { return new(tree.Element)(c, e) } - - if (c.value && c.value[0] === '&') { - return new(tree.Element)(c, null); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#:% \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-)?keyframes/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value ? value.trim() : ""; -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors( paths, context, this.selectors ); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value[0] === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('less/tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - styles[i].type = 'text/css'; - styles[i].innerHTML = tree.toCSS(); - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js deleted file mode 100644 index 182b526..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.4.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// -// LESS - Leaner CSS v1.1.4 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -// -// LESS - Leaner CSS v1.1.4 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function s(a){return a&&a.parentNode.removeChild(a)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){t("browser doesn't support AJAX.");return null}}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function p(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||o(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(h){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function o(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function n(b,c,e,f){var h=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=g&&g.getItem(i),k=g&&g.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=h.slice(0,h.lastIndexOf("/")+1)+i),q(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())p(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return u(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),s(document.getElementById("less-error-message:"+o(i)))}catch(a){u(a,i)}})}catch(h){u(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function m(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/)||s(/^(?:\d*\.)?\d+%/);if(a)return new e.Element(c,a);if(c.value&&c.value[0]==="&")return new e.Element(c,null)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#:% \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs -.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - less = {}; - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value ? value.trim() : ""; - this.index = index; -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors( paths, context, this.selectors ); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (less.mode === 'browser' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('../tree')); -require('./tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('./tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - try { - style.innerHTML = css; - } catch (_) { - style.styleSheets.cssText = css; - } - style.type = 'text/css'; - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js deleted file mode 100644 index 49949fb..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.5.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.1.5 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function s(a){var d,e,g,h,i,m,n,o;if(a instanceof Function)return a.call(l.parsers);if(typeof a=="string")d=b.charAt(c)===a?a:null,g=1,r();else{r();if(d=a.exec(j[f]))g=d[0].length;else return null}if(d){o=c+=g,m=c+j[f].length-g;while(c0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)!=="/")return;if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=='"'&&b.charAt(d)!=="'")return;f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)},keyword:function(){var a;if(a=s(/^[_A-Za-z-][_A-Za-z0-9-]*/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!(a=/^([\w-]+|%)\(/.exec(j[f])))return;a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)!=="u"||!s(/^url\(/))return;a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(d>57||d<45||d===47)return;if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=="`")return;f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!t(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i!=="."&&i!=="#")return;while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d,c)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,d=[],f,g,h,i;if(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/))return;if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!s(/^\(opacity=/i))return;if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,d;d=s(this.combinator),a=s(/^(?:\d+\.\d+|\d+)%/)||s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(d,a,c);if(d.value&&d.value.charAt(0)==="&")return new e.Element(d,null,c)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!s("["))return;if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,f;p();while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g==="."||g==="#"||g==="&")return;if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)!=="@")return;if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-|-moz-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(a.value=b[0]+(a.value.charAt(0)==="/"?a.value.slice(1):a.value)),this.value=a,this.paths=b)},a.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(b){return this.attrs?this:new a.URL(this.value.eval(b),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - less = {}; - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k) - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/) || $('keyframes')) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value ? value.trim() : ""; - this.index = index; -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors( paths, context, this.selectors ); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('../tree')); -require('./tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('./tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - try { - style.innerHTML = css; - } catch (_) { - style.styleSheets.cssText = css; - } - style.type = 'text/css'; - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js deleted file mode 100644 index a30623b..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.1.6.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.1.6 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),m=new e.Ruleset([],t(this.parsers.primary)),m.root=!0,m.toCSS=function(f){var g,h,i;return function(i,j){function p(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var k=[];i=i||{},typeof j=="object"&&!Array.isArray(j)&&(j=Object.keys(j).map(function(a){var b=j[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),k=[new e.Ruleset(null,j)]);try{var l=f.call(this,{frames:k}).toCSS([],{compress:i.compress||!1})}catch(m){h=b.split("\n"),g=p(m.index);for(var n=m.index,o=-1;n>=0&&b.charAt(n)!=="\n";n--)o++;throw{type:m.type,message:m.message,filename:a.filename,index:m.index,line:typeof g=="number"?g+1:null,callLine:m.call&&p(m.call)+1,callExtract:h[p(m.call)],stack:m.stack,column:o,extract:[h[g-1],h[g],h[g+1]]}}return i.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(l):i.compress?l.replace(/(\s)+/g,"$1"):l}}(m.eval);if(f=0&&b.charAt(x)!=="\n";x--)y++;w={name:"ParseError",message:"Syntax Error on line "+r,index:f,filename:a.filename,line:r,column:y,extract:[s[r-2],s[r-1],s[r]]}}this.imports.queue.length>0?o=function(){i(w,m)}:i(w,m)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var a,b,c=f;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;a=a[1].toLowerCase();if(a==="url")return null;f+=a.length;if(a==="alpha")return t(this.alpha);t("("),b=t(this.entities.arguments);if(!t(")"))return;if(a)return new e.Call(a,b,c)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!t(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=f;if(b.charAt(f)==="@"&&(a=t(/^@@?[\w-]+/)))return new e.Variable(a,c)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!u(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,g,h=f,i=b.charAt(f);if(i!=="."&&i!=="#")return;while(c=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(d,c,f)),d=t(">");t("(")&&(g=t(this.entities.arguments))&&t(")");if(a.length>0&&(t(";")||u("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,c=[],d,g,h,i;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||u(/^[^{]*(;|})/))return;if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)){if(h instanceof e.Variable)if(t(":"))if(i=t(this.expression))c.push({name:h.name,value:i});else throw new Error("Expected value");else c.push({name:h.name});else c.push({value:h});if(!t(","))break}if(!t(")"))throw new Error("Expected )");g=t(this.block);if(g)return new e.mixin.Definition(a,c,g)}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||u("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable)){if(!t(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/);if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}if(c===":"&&b.charAt(f+1)===":"){f+=2;while(b.charAt(f)===" ")f++;return new e.Combinator("::")}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var a=[],b,c,d;q();while(b=t(this.selector)){a.push(b),t(this.comment);if(!t(","))break;t(this.comment)}if(a.length>0&&(c=t(this.block)))return new e.Ruleset(a,c);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))&&t(";"))return new e.Import(a,p)},directive:function(){var a,c,d,g;if(b.charAt(f)!=="@")return;if(c=t(this["import"]))return c;if(a=t(/^@media|@page/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)||t("keyframes")){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!u(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - if (e && !that.error) { that.error = e } - callback(e, root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function getLocation(index) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: index ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var lines = input.split('\n'), - loc = getLocation(e.index), - line = loc.line, - col = loc.column; - - this.type = e.type || 'SyntaxError'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call) + 1); - this.callExtract = lines[getLocation(e.call)]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if (parser.imports.error) { throw parser.imports.error } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features); - } - } - }, - - mediaFeature: function () { - var nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var f, features = []; - while (f = $(this.mediaFeature)) { - features.push(f); - if (! $(',')) { break } - } - return features.length > 0 ? features : null; - }, - - media: function () { - var features; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Directive)('@media', rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - this.features = features && new(tree.Value)(features); - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.ruleset) { - this.ruleset.root = true; - return this.name + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - this.features = this.features && this.features.eval(env); - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features) { - var that = this; - - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root) { - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []); - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (root, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (root, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - - var template = ['
      ', - '
    • {0}
    • ', - '
    • {current}
    • ', - '
    • {2}
    • ', - '
    '].join('\n'); - - var elem = document.createElement('div'), timer, content; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    ' + href + " "; - - if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - template.replace(/\[(-?\d)\]/g, function (_, i) { - return (parseInt(e.line) + parseInt(i)) || ''; - }).replace(/\{(\d)\}/g, function (_, i) { - return e.extract[parseInt(i)] || ''; - }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + - e.extract[1].slice(e.column) + ''); - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #ee4444;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.ctx {', - 'color: #dd4444;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js deleted file mode 100644 index 84e9047..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.2.0.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.2.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e=["
      ",'
    • {0}
    • ',"
    • {current}
    • ",'
    • {2}
    • ',"
    "].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    '+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

    "+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cm&&(l[h]=l[h].slice(g-m),m=g)}function v(a){var c,d,e,f,i,j,k,o;if(a instanceof Function)return a.call(n.parsers);if(typeof a=="string")c=b.charAt(g)===a?a:null,e=1,u();else{u();if(c=a.exec(l[h]))e=c[0].length;else return null}if(c){o=g+=e,j=g+l[h].length-e;while(g=0&&b.charAt(c)!=="\n";c--)d++;return{line:a?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,c){var d=b.split("\n"),e=z(a.index),f=e.line,g=e.column;this.type=a.type||"SyntaxError",this.message=a.message,this.filename=a.filename||c.filename,this.index=a.index,this.line=typeof f=="number"?f+1:null,this.callLine=a.call&&z(a.call)+1,this.callExtract=d[z(a.call)],this.stack=a.stack,this.column=g,this.extract=[d[f-1],d[f],d[f+1]]}var b,g,h,i,j,k,l,m,n,o=this,q=function(){},r=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&q()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,n={imports:r,parse:function(e,i){var j,o,p,r,s,t,u=[],w,x=null;g=h=m=k=0,l=[],b=e.replace(/\r\n/g,"\n"),l=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],v(this.parsers.primary)),j.root=!0}catch(y){return i(new A(y,a))}j.toCSS=function(b){var e,g,h;return function(e,g){var h=[];e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var i=b.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(j){throw new A(j,a)}if(n.imports.error)throw n.imports.error;return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(i):e.compress?i.replace(/(\s)+/g,"$1"):i}}(j.eval);if(g=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:g,filename:a.filename,line:s,column:B,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?q=function(){i(x,j)}:i(x,j)},parsers:{primary:function(){var a,b=[];while((a=v(this.mixin.definition)||v(this.rule)||v(this.ruleset)||v(this.mixin.call)||v(this.comment)||v(this.directive))||v(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(g)!=="/")return;if(b.charAt(g+1)==="/")return new f.Comment(v(/^\/\/.*/),!0);if(a=v(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&v("~");if(a=v(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=v(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,b,c=g;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(l[h])))return;a=a[1].toLowerCase();if(a==="url")return null;g+=a.length;if(a==="alpha")return v(this.alpha);v("("),b=v(this.entities.arguments);if(!v(")"))return;if(a)return new f.Call(a,b,c)},arguments:function(){var a=[],b;while(b=v(this.entities.assignment)||v(this.expression)){a.push(b);if(!v(","))break}return a},literal:function(){return v(this.entities.dimension)||v(this.entities.color)||v(this.entities.quoted)},assignment:function(){var a,b;if((a=v(/^\w+(?=\s?=)/i))&&v("=")&&(b=v(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(b.charAt(g)!=="u"||!v(/^url\(/))return;return a=v(this.entities.quoted)||v(this.entities.variable)||v(this.entities.dataURI)||v(/^[-\w%@$\/.&=:;#+?~]+/)||"",w(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),r.paths)},dataURI:function(){var a;if(v(/^data:/)){a={},a.mime=v(/^[^\/]+\/[^,;)]+/)||"",a.charset=v(/^;\s*charset=[^,;)]+/)||"",a.base64=v(/^;\s*base64/)||"",a.data=v(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=g;if(b.charAt(g)==="@"&&(a=v(/^@@?[\w-]+/)))return new f.Variable(a,c)},color:function(){var a;if(b.charAt(g)==="#"&&(a=v(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(g);if(c>57||c<45||c===47)return;if(a=v(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&v("~");if(a=v(/^`([^`]*)`/))return new f.JavaScript(a[1],g,d)}},variable:function(){var a;if(b.charAt(g)==="@"&&(a=v(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!y(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=v(this.entity))&&v("/")&&(b=v(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,h=g,i=b.charAt(g),j=!1;if(i!=="."&&i!=="#")return;while(c=v(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,g)),d=v(">");v("(")&&(e=v(this.entities.arguments))&&v(")"),v(this.important)&&(j=!0);if(a.length>0&&(v(";")||y("}")))return new f.mixin.Call(a,e,h,j)},definition:function(){var a,c=[],d,e,h,i,j;if(b.charAt(g)!=="."&&b.charAt(g)!=="#"||y(/^[^{]*(;|})/))return;s();if(d=v(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=v(this.entities.variable)||v(this.entities.literal)||v(this.entities.keyword)){h instanceof f.Variable?v(":")?(i=w(this.expression,"expected expression"),c.push({name:h.name,value:i})):c.push({name:h.name}):c.push({value:h});if(!v(","))break}w(")"),v(/^when/)&&(j=w(this.conditions,"expected condition")),e=v(this.block);if(e)return new f.mixin.Definition(a,c,e,j);t()}}},entity:function(){return v(this.entities.literal)||v(this.entities.variable)||v(this.entities.url)||v(this.entities.call)||v(this.entities.keyword)||v(this.entities.javascript)||v(this.comment)},end:function(){return v(";")||y("}")},alpha:function(){var a;if(!v(/^\(opacity=/i))return;if(a=v(/^\d+/)||v(this.entities.variable))return w(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=v(this.combinator),a=v(/^(?:\d+\.\d+|\d+)%/)||v(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||v("*")||v(this.attribute)||v(/^\([^)@]+\)/),a||v("(")&&(d=v(this.entities.variable))&&v(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,g);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,g)},combinator:function(){var a,c=b.charAt(g);if(c===">"||c==="+"||c==="~"){g++;while(b.charAt(g)===" ")g++;return new f.Combinator(c)}if(c==="&"){a="&",g++,b.charAt(g)===" "&&(a="& ");while(b.charAt(g)===" ")g++;return new f.Combinator(a)}if(c===":"&&b.charAt(g+1)===":"){g+=2;while(b.charAt(g)===" ")g++;return new f.Combinator("::")}return b.charAt(g-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,c,d=[],e,h;while(c=v(this.element)){e=b.charAt(g),d.push(c);if(e==="{"||e==="}"||e===";"||e===",")break}if(d.length>0)return new f.Selector(d)},tag:function(){return v(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||v("*")},attribute:function(){var a="",b,c,d;if(!v("["))return;if(b=v(/^[a-zA-Z-]+/)||v(this.entities.quoted))(d=v(/^[|~*$^]?=/))&&(c=v(this.entities.quoted)||v(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!v("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(v("{")&&(a=v(this.primary))&&v("}"))return a},ruleset:function(){var a=[],b,c,d;s();while(b=v(this.selector)){a.push(b),v(this.comment);if(!v(","))break;v(this.comment)}if(a.length>0&&(c=v(this.block)))return new f.Ruleset(a,c);k=g,t()},rule:function(){var a,c,d=b.charAt(g),e,i;s();if(d==="."||d==="#"||d==="&")return;if(a=v(this.variable)||v(this.property)){a.charAt(0)!="@"&&(i=/^([^@+\/'"*`(;{}-]*);/.exec(l[h]))?(g+=i[0].length-1,c=new f.Anonymous(i[1])):a==="font"?c=v(this.font):c=v(this.value),e=v(this.important);if(c&&v(this.end))return new f.Rule(a,c,e,j);k=g,t()}},"import":function(){var a,b;if(v(/^@import\s+/)&&(a=v(this.entities.quoted)||v(this.entities.url))){b=v(this.mediaFeatures);if(v(";"))return new f.Import(a,r,b)}},mediaFeature:function(){var a=[];do if(e=v(this.entities.keyword))a.push(e);else if(v("(")){p=v(this.property),e=v(this.entity);if(!v(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,g,!0)));else if(e)a.push(new f.Paren(e));else return null}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=v(this.mediaFeature)){b.push(a);if(!v(","))break}return b.length>0?b:null},media:function(){var a;if(v(/^@media/)){a=v(this.mediaFeatures);if(rules=v(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,c,d,e,h,i;if(b.charAt(g)!=="@")return;if(c=v(this["import"])||v(this.media))return c;if(a=v(/^@page|@keyframes/)||v(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){e=(v(/^[^{]+/)||"").trim();if(d=v(this.block))return new f.Directive(a+" "+e,d)}else if(a=v(/^@[-a-z]+/))if(a==="@font-face"){if(d=v(this.block))return new f.Directive(a,d)}else if((c=v(this.entity))&&v(";"))return new f.Directive(a,c)},font:function(){var a=[],b=[],c,d,e,g;while(g=v(this.shorthand)||v(this.entity))b.push(g);a.push(new f.Expression(b));if(v(","))while(g=v(this.expression)){a.push(g);if(!v(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=v(this.expression)){b.push(a);if(!v(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(b.charAt(g)==="!")return v(/^! *important/)},sub:function(){var a;if(v("(")&&(a=v(this.expression))&&v(")"))return a},multiplication:function(){var a,b,c,d;if(a=v(this.operand)){while(!y(/^\/\*/)&&(c=v("/")||v("*"))&&(b=v(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,e;if(a=v(this.multiplication)){while((d=v(/^[-+]\s+/)||b.charAt(g-1)!=" "&&(v("+")||v("-")))&&(c=v(this.multiplication)))e=new f.Operation(d,[e||a,c]);return e||a}},conditions:function(){var a,b,c=g,d;if(a=v(this.condition)){while(v(",")&&(b=v(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=g,h=!1;v(/^not/)&&(h=!0),w("(");if(a=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))return(d=v(/^(?:>=|=<|[<=>])/))?(b=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))?c=new f.Condition(d,a,b,e,h):x("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,h),w(")"),v(/^and/)?new f.Condition("and",c,v(this.condition)):c},operand:function(){var a,c=b.charAt(g+1);b.charAt(g)==="-"&&(c==="@"||c==="(")&&(a=v("-"));var d=v(this.sub)||v(this.entities.dimension)||v(this.entities.color)||v(this.entities.variable)||v(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=v(this.addition)||v(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=v(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d){var e=this;this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a,b){e.root=b})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&r(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - callback(e, root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[e.filename]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input) + 1); - this.callExtract = lines[getLocation(e.call, input)]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, index); - } - } - }, - - mediaFeature: function () { - var nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var f, features = []; - while (f = $(this.mediaFeature)) { - features.push(f); - if (! $(',')) { break } - } - return features.length > 0 ? features : null; - }, - - media: function () { - var features; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Directive)('@media', rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - this.features = features && new(tree.Value)(features); - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.ruleset) { - this.ruleset.root = true; - return this.name + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - this.features = this.features && this.features.eval(env); - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, index) { - var that = this; - - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root) { - if (e) { e.index = index } - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []); - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - var filename = href.match(/([^\/]+)$/)[1]; - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: filename - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filename + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - '
      ' + error.join('') + '
    '; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js deleted file mode 100644 index 89b7637..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.2.1.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.2.1 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&B(a.call,c)+1,this.callExtract=g[B(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return a.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - callback(e, root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function basename(pathname) { - if (less.mode === 'node') { - return require('path').basename(pathname); - } else { - return pathname.match(/[^\/]+$/)[0]; - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[basename(e.filename)]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input) + 1); - this.callExtract = lines[getLocation(e.call, input)]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)\\]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, index); - } - } - }, - - mediaFeature: function () { - var nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var f, features = []; - while (f = $(this.mediaFeature)) { - features.push(f); - if (! $(',')) { break } - } - return features.length > 0 ? features : null; - }, - - media: function () { - var features; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Directive)('@media', rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - this.features = features && new(tree.Value)(features); - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.ruleset) { - this.ruleset.root = true; - return this.name + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - this.features = this.features && this.features.eval(env); - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, index) { - var that = this; - - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root) { - if (e) { e.index = index } - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []); - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join( env.compress ? ',' : ',\n'); - - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - var filename = href.match(/([^\/]+)$/)[1]; - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: filename - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filename + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - '
      ' + error.join('') + '
    '; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js deleted file mode 100644 index 55042ec..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.2.2.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.2.2 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function D(a,b){var c=B(a,b),d=C(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&C(a.call,c)+1,this.callExtract=g[C(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)\\]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=a[0],k;for(var l=0,m,n;l0&&(x=new D({index:l,type:"Parse",message:"missing closing `}`",filename:b.filename},b)),a.map(function(a){return a.join("")})}([[]]);if(x)return e(x);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new D(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new D(k,b)}if(i=o.imports.error)throw i instanceof D?i:new D(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - callback(e, root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function basename(pathname) { - if (less.mode === 'node') { - return require('path').basename(pathname); - } else { - return pathname.match(/[^\/]+$/)[0]; - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[basename(e.filename)]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)\\]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args || [], index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); - } - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules, env.strictImports); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, index); - } - } - }, - - mediaFeature: function () { - var e, p, nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Media)(rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, index) { - var that = this; - - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root) { - if (e) { e.index = index } - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); -(function (tree) { - -tree.Media = function (value, features) { - var el = new(tree.Element)('&', null, 0), - selectors = [new(tree.Selector)([el])]; - - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; -}; -tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); - - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var el = new(tree.Element)('&', null, 0); - var selectors = [new(tree.Selector)([el])]; - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs; - - for (var i = 0, val, name; i < this.params.length; i++) { - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - } - - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join( env.compress ? ',' : ',\n'); - - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - var filename = href.match(/([^\/]+)$/)[1]; - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: filename - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filename + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - '
      ' + error.join('') + '
    '; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js deleted file mode 100644 index 309bf55..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.3.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,b){var c=y(a,b),d=z(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&z(a.call,c).line+1,this.callExtract=g[z(a.call,c).line],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var b,f,g,h,i,j,k,l,m,n=this,o=function(){},p=this.imports={paths:a&&a.paths||[],queue:[],files:{},contents:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d,f){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,e.contents[b]=f,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&o()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,m={imports:p,parse:function(h,i){var n,p,q,r,s,u,v=[],w,x=null;f=g=l=j=0,b=h.replace(/\r\n/g,"\n"),k=function(c){var d=0,e=/[^"'`\{\}\/\(\)\\]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=c[0],k;for(var l=0,m,n;l0&&(x=new A({index:l,type:"Parse",message:"missing closing `}`",filename:a.filename},a)),c.map(function(a){return a.join("")})}([[]]);if(x)return i(x);try{n=new e.Ruleset([],t(this.parsers.primary)),n.root=!0}catch(y){return i(new A(y,a))}n.toCSS=function(b){var f,g,h;return function(f,g){var h=[],i;f=f||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),h=[new e.Ruleset(null,g)]);try{var j=b.call(this,{frames:h}).toCSS([],{compress:f.compress||!1})}catch(k){throw new A(k,a)}if(i=m.imports.error)throw i instanceof A?i:new A(i,a);return f.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):f.compress?j.replace(/(\s)+/g,"$1"):j}}(n.eval);if(f=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:f,filename:a.filename,line:s,column:B,extract:[u[s-2],u[s-1],u[s]]}}this.imports.queue.length>0?o=function(){i(x,n)}:i(x,n)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var b,c,d=f;if(!(b=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;b=b[1].toLowerCase();if(b==="url")return null;f+=b.length;if(b==="alpha")return t(this.alpha);t("("),c=t(this.entities.arguments);if(!t(")"))return;if(b)return new e.Call(b,c,d,a.filename)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;return a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"",u(")"),new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var c,d=f;if(b.charAt(f)==="@"&&(c=t(/^@@?[\w-]+/)))return new e.Variable(c,d,a.filename)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!w(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var c=[],d,g,h,i=f,j=b.charAt(f),k=!1;if(j!=="."&&j!=="#")return;while(d=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))c.push(new e.Element(g,d,f)),g=t(">");t("(")&&(h=t(this.entities.arguments))&&t(")"),t(this.important)&&(k=!0);if(c.length>0&&(t(";")||w("}")))return new e.mixin.Call(c,h||[],i,a.filename,k)},definition:function(){var a,c=[],d,g,h,i,j,k=!1;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||w(/^[^{]*(;|})/))return;q();if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];do{if(b.charAt(f)==="."&&t(/^\.{3}/)){k=!0;break}if(!(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)))break;if(h instanceof e.Variable)if(t(":"))i=u(this.expression,"expected expression"),c.push({name:h.name,value:i});else{if(t(/^\.{3}/)){c.push({name:h.name,variadic:!0}),k=!0;break}c.push({name:h.name})}else c.push({value:h})}while(t(","));u(")"),t(/^when/)&&(j=u(this.conditions,"expected condition")),g=t(this.block);if(g)return new e.mixin.Definition(a,c,g,j,k);r()}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||w("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable))return u(")"),new e.Alpha(a)},element:function(){var a,b,c,d;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/),a||t("(")&&(d=t(this.entities.variable))&&t(")")&&(a=new e.Paren(d));if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;if(t("("))return a=t(this.entity),u(")"),new e.Selector([new e.Element("",a,f)]);while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var b=[],c,d,g;q();while(c=t(this.selector)){b.push(c),t(this.comment);if(!t(","))break;t(this.comment)}if(b.length>0&&(d=t(this.block)))return new e.Ruleset(b,d,a.strictImports);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a,b,c=f;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))){b=t(this.mediaFeatures);if(t(";"))return new e.Import(a,p,b,c)}},mediaFeature:function(){var a,b,c=[];do if(a=t(this.entities.keyword))c.push(a);else if(t("(")){b=t(this.property),a=t(this.entity);if(!t(")"))return null;if(b&&a)c.push(new e.Paren(new e.Rule(b,a,null,f,!0)));else if(a)c.push(new e.Paren(a));else return null}while(a);if(c.length>0)return new e.Expression(c)},mediaFeatures:function(){var a,b=[];do if(a=t(this.mediaFeature)){b.push(a);if(!t(","))break}else if(a=t(this.entities.variable)){b.push(a);if(!t(","))break}while(a);return b.length>0?b:null},media:function(){var a,b;if(t(/^@media/)){a=t(this.mediaFeatures);if(b=t(this.block))return new e.Media(b,a)}},directive:function(){var a,c,d,g,h,i;if(b.charAt(f)!=="@")return;if(c=t(this["import"])||t(this.media))return c;if(a=t(/^@page|@keyframes/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!w(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},conditions:function(){var a,b,c=f,d;if(a=t(this.condition)){while(t(",")&&(b=t(this.condition)))d=new e.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,g=f,h=!1;t(/^not/)&&(h=!0),u("(");if(a=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))return(d=t(/^(?:>=|=<|[<=>])/))?(b=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))?c=new e.Condition(d,a,b,g,h):v("expected expression"):c=new e.Condition("=",a,new e.Keyword("true"),g,h),u(")"),t(/^and/)?new e.Condition("and",c,t(this.condition)):c},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e1){var d=new a.Element("&",null,0),e=[new a.Selector([d])];c=new a.Ruleset(e,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(a.length===0)return[];if(a.length===1)return a[0];var b=[],c=this.permute(a.slice(1));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;gthis.params.length)return!1;if(this.required>0&&c>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c,d,e){b&&p(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // Top parser on an import tree must be sure there is one "env" - // which will then be passed arround by reference. - var env = env || { }; - if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: env.contents, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - - var imported = path in that.files; - - that.files[path] = root; // Store the root - - if (e && !that.error) { that.error = e } - - callback(e, root, imported); - - if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - function isWhitespace(c) { - // Could change to \s? - var code = c.charCodeAt(0); - return code === 32 || code === 10 || code === 9; - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, index, k; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - skipWhitespace(length); - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function skipWhitespace(length) { - var oldi = i, oldj = j, - endIndex = i + chunks[j].length, - mem = i += length; - - while (i < endIndex) { - if (! isWhitespace(input.charAt(i))) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - return oldi !== i || oldj !== j; - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[e.filename]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function getFileName(e) { - if(less.mode === 'browser' || less.mode === 'rhino') - return e.filename; - else - return require('path').resolve(e.filename); - } - - function getDebugInfo(index, inputStream, e) { - return { - lineNumber: getLocation(index, inputStream).line + 1, - fileName: getFileName(e) - }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Remove potential UTF Byte Order Mark - input = input.replace(/^\uFEFF/, ''); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function (e) { - if (e) callback(e); - else callback(null, root); - }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, nameLC, args, alpha_ret, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1]; - nameLC = name.toLowerCase(); - - if (nameLC === 'url') { return null } - else { i += name.length } - - if (nameLC === 'alpha') { - alpha_ret = $(this.alpha); - if(typeof alpha_ret !== 'undefined') { - return alpha_ret; - } - } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.ratio) || - $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value != null || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // A variable entity useing the protective {} e.g. @{var} - variableCurly: function () { - var name, curly, index = i; - - if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { - return new(tree.Variable)("@" + curly[1], index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // A Ratio - // - // 16/9 - // - ratio: function () { - var value, c = input.charCodeAt(i); - if (c > 57 || c < 48) return; - - if (value = $(/^(\d+\/\d+)/)) { - return new(tree.Ratio)(value[1]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - save(); - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - - restore(); - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; - - if (s !== '.' && s !== '#') { return } - - save(); // stop us absorbing part of an invalid selector - - while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - if ($('(')) { - while (arg = $(this.expression)) { - value = arg; - name = null; - - // Variable - if (arg.value.length == 1) { - var val = arg.value[0]; - if (val instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - name = val.name; - } else { - throw new(Error)("Expected value"); - } - } - } - } - - args.push({ name: name, value: value }); - - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - } - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - - restore(); - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - // .mixincall("@{a}"); - // looks a bit like a mixin definition.. so we have to be nice and restore - if (!$(')')) { - furthest = i; - restore(); - } - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || - $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); - - if (! e) { - if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { - e = new(tree.Paren)(v); - } - } - - if (e) { return new(tree.Element)(c, e, i) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i).match(/\s/)) { i++ } - return new(tree.Combinator)(c); - } else if (input.charAt(i - 1).match(/\s/)) { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - // depreciated, will be removed soon - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); - } - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match, debugInfo; - save(); - - if (env.dumpLineNumbers) - debugInfo = getDebugInfo(i, input, env); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); - if (env.dumpLineNumbers) - ruleset.debugInfo = debugInfo; - return ruleset; - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - - save(); - - var dir = $(/^@import(?:-(once))?\s+/); - - if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); - } - } - - restore(); - }, - - mediaFeature: function () { - var e, p, nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules, media, debugInfo; - - if (env.dumpLineNumbers) - debugInfo = getDebugInfo(i, input, env); - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - media = new(tree.Media)(rules, features); - if(env.dumpLineNumbers) - media.debugInfo = debugInfo; - return media; - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, identifier, e, nodes, nonVendorSpecificName, - hasBlock, hasIdentifier; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } - - save(); - - name = $(/^@[a-z-]+/); - - nonVendorSpecificName = name; - if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { - nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); - } - - switch(nonVendorSpecificName) { - case "@font-face": - hasBlock = true; - break; - case "@viewport": - case "@top-left": - case "@top-left-corner": - case "@top-center": - case "@top-right": - case "@top-right-corner": - case "@bottom-left": - case "@bottom-left-corner": - case "@bottom-center": - case "@bottom-right": - case "@bottom-right-corner": - case "@left-top": - case "@left-middle": - case "@left-bottom": - case "@right-top": - case "@right-middle": - case "@right-bottom": - hasBlock = true; - break; - case "@page": - case "@document": - case "@supports": - case "@keyframes": - hasBlock = true; - hasIdentifier = true; - break; - } - - if (hasIdentifier) { - name += " " + ($(/^[^{]+/) || '').trim(); - } - - if (hasBlock) - { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else { - if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - - restore(); - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ - loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - red: function (color) { - return new(tree.Dimension)(color.rgb[0]); - }, - green: function (color) { - return new(tree.Dimension)(color.rgb[1]); - }, - blue: function (color) { - return new(tree.Dimension)(color.rgb[2]); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - luma: function (color) { - return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + - 0.7152 * (color.rgb[1]/255) + - 0.0722 * (color.rgb[2]/255)) - * color.alpha * 100), '%'); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - if (!weight) { - weight = new(tree.Dimension)(50); - } - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - contrast: function (color, dark, light, threshold) { - if (typeof light === 'undefined') { - light = this.rgba(255, 255, 255, 1.0); - } - if (typeof dark === 'undefined') { - dark = this.rgba(0, 0, 0, 1.0); - } - if (typeof threshold === 'undefined') { - threshold = 0.43; - } else { - threshold = threshold.value; - } - if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { - return light; - } else { - return dark; - } - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n, f) { - var fraction = typeof(f) === "undefined" ? 0 : f.value; - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); - } else if (typeof(n) === 'number') { - return n.toFixed(fraction); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - }, - - /* Blending modes */ - - multiply: function(color1, color2) { - var r = color1.rgb[0] * color2.rgb[0] / 255; - var g = color1.rgb[1] * color2.rgb[1] / 255; - var b = color1.rgb[2] * color2.rgb[2] / 255; - return this.rgb(r, g, b); - }, - screen: function(color1, color2) { - var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; - var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; - var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - overlay: function(color1, color2) { - var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; - var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; - var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - softlight: function(color1, color2) { - var t = color2.rgb[0] * color1.rgb[0] / 255; - var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; - t = color2.rgb[1] * color1.rgb[1] / 255; - var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; - t = color2.rgb[2] * color1.rgb[2] / 255; - var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; - return this.rgb(r, g, b); - }, - hardlight: function(color1, color2) { - var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; - var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; - var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - difference: function(color1, color2) { - var r = Math.abs(color1.rgb[0] - color2.rgb[0]); - var g = Math.abs(color1.rgb[1] - color2.rgb[1]); - var b = Math.abs(color1.rgb[2] - color2.rgb[2]); - return this.rgb(r, g, b); - }, - exclusion: function(color1, color2) { - var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; - var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; - var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - average: function(color1, color2) { - var r = (color1.rgb[0] + color2.rgb[0]) / 2; - var g = (color1.rgb[1] + color2.rgb[1]) / 2; - var b = (color1.rgb[2] + color2.rgb[2]) / 2; - return this.rgb(r, g, b); - }, - negation: function(color1, color2) { - var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); - var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); - var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); - return this.rgb(r, g, b); - }, - tint: function(color, amount) { - return this.mix(this.rgb(255,255,255), color, amount); - }, - shade: function(color, amount) { - return this.mix(this.rgb(0, 0, 0), color, amount); - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - // 'transparent':'rgba(0,0,0,0)', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this }, - compare: function (x) { - if (!x.toCSS) { - return -1; - } - - var left = this.toCSS(), - right = x.toCSS(); - - if (left === right) { - return 0; - } - - return left < right ? -1 : 1; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { - return new(tree.Assignment)(this.key, this.value.eval(env)); - } - return this; - } -}; - -})(require('../tree'));(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - }, - compare: function (x) { - if (!x.rgb) { - return -1; - } - - return (x.rgb[0] === this.rgb[0] && - x.rgb[1] === this.rgb[1] && - x.rgb[2] === this.rgb[2] && - x.alpha === this.alpha) ? 0 : -1; - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - var evaldDirective = this; - if (this.ruleset) { - env.frames.unshift(this); - evaldDirective = new(tree.Directive)(this.name); - evaldDirective.ruleset = this.ruleset.eval(env); - env.frames.shift(); - } - return evaldDirective; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); - if (value == '' && this.combinator.value.charAt(0) == '&') { - return ''; - } else { - return this.combinator.toCSS(env || {}) + value; - } -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, once, index) { - var that = this; - - this.once = once; - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root, imported) { - if (e) { e.index = index } - if (imported && that.once) that.skip = imported; - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.skip) return []; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); -(function (tree) { - -tree.Media = function (value, features) { - var selectors = this.emptySelectors(); - - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; -}; -tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); - - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - if(this.debugInfo) { - this.ruleset.debugInfo = this.debugInfo; - media.debugInfo = this.debugInfo; - } - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - emptySelectors: function() { - var el = new(tree.Element)('', '&', 0); - return [new(tree.Selector)([el])]; - }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var selectors = this.emptySelectors(); - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; - } - }, - bubbleSelectors: function (selectors) { - this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { - return { name: a.name, value: a.value.eval(env) }; - }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs, arg; - - for (var i = 0, val, name; i < this.params.length; i++) { - arg = args && args[i] - - if (arg && arg.name) { - frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); - args.splice(i, 1); - i--; - continue; - } - - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].value.eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (arg && arg.value) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push((args[i] && args[i].value) || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - } - - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - }, - compare: function (x) { - if (!x.toCSS) { - return -1; - } - - var left = this.toCSS(), - right = x.toCSS(); - - if (left === right) { - return 0; - } - - return left < right ? -1 : 1; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ratio = function (value) { - this.value = value; -}; -tree.Ratio.prototype = { - toCSS: function (env) { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - var rules = []; - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - if(this.debugInfo) { - ruleset.debugInfo = this.debugInfo; - } - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - rules = rules.concat(ruleset.rules[i].eval(env)); - } else { - rules.push(ruleset.rules[i]); - } - } - ruleset.rules = rules; - rules = []; - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - rules = rules.concat(ruleset.rules[i].eval(env)); - } else { - rules.push(ruleset.rules[i]); - } - } - ruleset.rules = rules; - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - if (env.mediaBlocks) { - for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { - env.mediaBlocks[i].bubbleSelectors(selectors); - } - } - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - _rules = [], // - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - debugInfo, // Line number debugging - rule; - - if (! this.root) { - this.joinSelectors(paths, context, this.selectors); - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - debugInfo = tree.debugInfo(env, this); - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : ',\n'); - - // Remove duplicates - for (var i = rules.length - 1; i >= 0; i--) { - if (_rules.indexOf(rules[i]) === -1) { - _rules.unshift(rules[i]); - } - } - rules = _rules; - - css.push(debugInfo + selector + - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - - var i, j, k, - hasParentSelector, newSelectors, el, sel, parentSel, - newSelectorPath, afterParentJoin, newJoinedSelector, - newJoinedSelectorEmpty, lastSelector, currentElements, - selectorsMultiplied; - - for (i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.value === '&') { - hasParentSelector = true; - } - } - - if (!hasParentSelector) { - if (context.length > 0) { - for(i = 0; i < context.length; i++) { - paths.push(context[i].concat(selector)); - } - } - else { - paths.push([selector]); - } - return; - } - - // The paths are [[Selector]] - // The first list is a list of comma seperated selectors - // The inner list is a list of inheritance seperated selectors - // e.g. - // .a, .b { - // .c { - // } - // } - // == [[.a] [.c]] [[.b] [.c]] - // - - // the elements from the current selector so far - currentElements = []; - // the current list of new selectors to add to the path. - // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors - // by the parents - newSelectors = [[]]; - - for (i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - // non parent reference elements just get added - if (el.value !== "&") { - currentElements.push(el); - } else { - // the new list of selectors to add - selectorsMultiplied = []; - - // merge the current list of non parent selector elements - // on to the current list of selectors to add - if (currentElements.length > 0) { - this.mergeElementsOnToSelectors(currentElements, newSelectors); - } - - // loop through our current selectors - for(j = 0; j < newSelectors.length; j++) { - sel = newSelectors[j]; - // if we don't have any parent paths, the & might be in a mixin so that it can be used - // whether there are parents or not - if (context.length == 0) { - // the combinator used on el should now be applied to the next element instead so that - // it is not lost - if (sel.length > 0) { - sel[0].elements = sel[0].elements.slice(0); - sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); - } - selectorsMultiplied.push(sel); - } - else { - // and the parent selectors - for(k = 0; k < context.length; k++) { - parentSel = context[k]; - // We need to put the current selectors - // then join the last selector's elements on to the parents selectors - - // our new selector path - newSelectorPath = []; - // selectors from the parent after the join - afterParentJoin = []; - newJoinedSelectorEmpty = true; - - //construct the joined selector - if & is the first thing this will be empty, - // if not newJoinedSelector will be the last set of elements in the selector - if (sel.length > 0) { - newSelectorPath = sel.slice(0); - lastSelector = newSelectorPath.pop(); - newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); - newJoinedSelectorEmpty = false; - } - else { - newJoinedSelector = new(tree.Selector)([]); - } - - //put together the parent selectors after the join - if (parentSel.length > 1) { - afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); - } - - if (parentSel.length > 0) { - newJoinedSelectorEmpty = false; - - // join the elements so far with the first part of the parent - newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); - newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); - } - - if (!newJoinedSelectorEmpty) { - // now add the joined selector - newSelectorPath.push(newJoinedSelector); - } - - // and the rest of the parent - newSelectorPath = newSelectorPath.concat(afterParentJoin); - - // add that to our new set of selectors - selectorsMultiplied.push(newSelectorPath); - } - } - } - - // our new selectors has been multiplied, so reset the state - newSelectors = selectorsMultiplied; - currentElements = []; - } - } - - // if we have any elements left over (e.g. .a& .b == .b) - // add them on to all the current selectors - if (currentElements.length > 0) { - this.mergeElementsOnToSelectors(currentElements, newSelectors); - } - - for(i = 0; i < newSelectors.length; i++) { - paths.push(newSelectors[i]); - } - }, - - mergeElementsOnToSelectors: function(elements, selectors) { - var i, sel; - - if (selectors.length == 0) { - selectors.push([ new(tree.Selector)(elements) ]); - return; - } - - for(i = 0; i < selectors.length; i++) { - sel = selectors[i]; - - // if the previous thing in sel is a parent this needs to join on to it - if (sel.length > 0) { - sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); - } - else { - sel.push(new(tree.Selector)(elements)); - } - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - if (this.elements[0].combinator.value === "") { - this._css = ' '; - } else { - this._css = ''; - } - - this._css += this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); - - return this._css; -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - this.value = val; - this.paths = paths; -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + this.value.toCSS() + ")"; - }, - eval: function (ctx) { - var val = this.value.eval(ctx); - - // Add the base path if the URL is relative and we are either - // a.) in the browser or - // b.) we have a relative file URL - if ((this.paths.length > 0) && - (typeof window !== 'undefined' || !/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0])) && - (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value))) { - var path = this.paths[0].slice(-1) === '/' ? this.paths[0] : this.paths[0] + '/'; - var v = path + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - val = new(tree.Anonymous)(v); - } - - return new(tree.URL)(val, this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.debugInfo = function(env, ctx) { - var result=""; - if (env.dumpLineNumbers && !env.compress) { - switch(env.dumpLineNumbers) { - case 'comments': - result = tree.debugInfo.asComment(ctx); - break; - case 'mediaquery': - result = tree.debugInfo.asMediaQuery(ctx); - break; - case 'all': - result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); - break; - } - } - return result; -}; - -tree.debugInfo.asComment = function(ctx) { - return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; -}; - -tree.debugInfo.asMediaQuery = function(ctx) { - return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; -}; - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); -// -// browser.js - client-side engine -// - -var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = less.async || false; -less.fileAsync = less.fileAsync || false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); - if (dumpLineNumbers) { - less.dumpLineNumbers = dumpLineNumbers[1]; - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)({ - filename: document.location.href.replace(/#.*$/, ''), - dumpLineNumbers: less.dumpLineNumbers - }).parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var contents = sheet.contents || {}; // Passing a ref to top importing parser content cache trough 'sheet' arg. - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^[a-z-]+:/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - contents[href] = data; // Updating top importing parser content cache - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: href, - 'contents': contents, // Passing top importing parser content cache ref down. - dumpLineNumbers: less.dumpLineNumbers - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - if( sheet.media ){ css.media = sheet.media; } - css.id = id; - var nextEl = sheet && sheet.nextSibling || null; - document.getElementsByTagName('head')[0].insertBefore(css, nextEl); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - try { - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } catch(e) { - //TODO - could do with adding more robust error handling - log('failed to save'); - } - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? less.fileAsync : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol && !less.fileAsync) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - var filenameNoPath = filename.match(/([^\/]+)$/)[1]; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filenameNoPath + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - '
      ' + error.join('') + '
    '; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - -// amd.js -// -// Define Less as an AMD module. -if (typeof define === "function" && define.amd) { - define("less", [], function () { return less; } ); -} -})(window); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js b/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js deleted file mode 100644 index 42b67f0..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-1.3.0e.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.3.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(e,t){function n(t){return e.less[t.split("/")[1]]}function h(){var e=document.getElementsByTagName("style");for(var t=0;t0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&u){w("saving "+i+" to cache.");try{u.setItem(i,e),u.setItem(i+":timestamp",n)}catch(a){w("failed to save")}}}function g(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var o=y(),u=s?r.fileAsync:r.async;typeof o.overrideMimeType=="function"&&o.overrideMimeType("text/css"),o.open("GET",e,u),o.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),o.send(null),s&&!r.fileAsync?o.status===0||o.status>=200&&o.status<300?n(o.responseText):i(o.status,e):u?o.onreadystatechange=function(){o.readyState==4&&a(o,n,i)}:a(o,n,i)}function y(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return w("browser doesn't support AJAX."),null}}function b(e){return e&&e.parentNode.removeChild(e)}function w(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function E(e,t){var n="less-error-message:"+v(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,m([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={});var v=function(){},m=this.imports={paths:t&&t.paths||[],queue:[],files:{},contents:t.contents,mime:t&&t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r){i.queue.splice(i.queue.indexOf(e),1);var s=e in i.files;i.files[e]=r,t&&!i.error&&(i.error=t),n(t,r,s),i.queue.length===0&&v(t)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0&&(x=new O({index:c,type:"Parse",message:"missing closing `}`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("./cssmin").compressor.cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),m.paths)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<45||t===47)return;if(e=E(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a,f=o,l=s.charAt(o),c,h,p=!1;if(l!=="."&&l!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){while(a=E(this.expression)){h=a,c=null;if(a.value.length==1){var d=a.value[0];if(d instanceof i.Variable&&E(":")){if(!(h=E(this.expression)))throw new Error("Expected value");c=d.name}}u.push({name:c,value:h});if(!E(","))break}if(!E(")"))throw new Error("Expected )")}E(this.important)&&(p=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,u,f,t.filename,p);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*(;|})/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0;break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(","));E(")")||(l=o,y()),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^)@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),x(")"),new i.Selector([new i.Element("",e,o)]);while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===",")break}if(n.length>0)return new i.Selector(n)},tag:function(){return E(/^[A-Za-z][A-Za-z-]*[0-9]?/)||E("*")},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,t,n=o;g();var r=E(/^@import(?:-(once))?\s+/);if(r&&(e=E(this.entities.quoted)||E(this.entities.url))){t=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,t,r[1]==="once",n)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,t,n,r,u,a,f,l,c;if(s.charAt(o)!=="@")return;if(t=E(this["import"])||E(this.media))return t;g(),e=E(/^@[a-z-]+/),f=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(f="@"+e.slice(e.indexOf("-",2)+1));switch(f){case"@font-face":l=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":l=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":l=!0,c=!0}c&&(e+=" "+(E(/^[^{]+/)||"").trim());if(l){if(n=E(this.block))return new i.Directive(e,n)}else if((t=E(this.entity))&&E(";"))return new i.Directive(e,t);y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/\*/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),d({href:e,title:e,type:r.mime,contents:r.contents},function(i){i&&typeof r.errback=="function"?r.errback.call(null,e,t,n,r):n.apply(null,arguments)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function r(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,r,i,s){var o=[t,r,i].map(function(e){return n(e)}),s=n(s);return new e.Color(o,s)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,r,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=n(e)%360/360,t=n(t),r=n(r),i=n(i);var s=r<=.5?r*(t+1):r+t-r*t,o=r*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var i=e.toHSL();return i.s+=n.value/100,i.s=r(i.s),t(i)},desaturate:function(e,n){var i=e.toHSL();return i.s-=n.value/100,i.s=r(i.s),t(i)},lighten:function(e,n){var i=e.toHSL();return i.l+=n.value/100,i.l=r(i.l),t(i)},darken:function(e,n){var i=e.toHSL();return i.l-=n.value/100,i.l=r(i.l),t(i)},fadein:function(e,n){var i=e.toHSL();return i.a+=n.value/100,i.a=r(i.a),t(i)},fadeout:function(e,n){var i=e.toHSL();return i.a-=n.value/100,i.a=r(i.a),t(i)},fade:function(e,n){var i=e.toHSL();return i.a=n.value/100,i.a=r(i.a),t(i)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t, -n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s){var o=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),t instanceof e.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css(\?.*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&o.once&&(o.skip=r),o.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?"@import "+this._path.toCSS()+t+";\n":""},eval:function(t){var n,r=this.features&&this.features.eval(t);if(this.skip)return[];if(this.css)return this;n=new e.Ruleset([],this.root.rules.slice(0));for(var i=0;i1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){n=this.arguments&&this.arguments.map(function(t){return{name:t.name,value:t.value.eval(e)}});for(var o=0;othis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(t,e)].concat(t.frames)}))return!1;r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements.length,n=e.elements.length,r=Math.min(t,n);if(t0&&(typeof e!="undefined"||!/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0]))&&typeof r.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(r.value)){var i=this.paths[0].slice(-1)==="/"?this.paths[0]:this.paths[0]+"/",s=i+(r.value.charAt(0)==="/"?r.value.slice(1):r.value);r=new t.Anonymous(s)}return new t.URL(r,this.paths)}}}(n("../tree")),function(e){e.Value=function(e){this.value=e,this.is="value"},e.Value.prototype={eval:function(t){return this.value.length===1?this.value[0].eval(t):new e.Value(this.value.map(function(e){return e.eval(t)}))},toCSS:function(e){return this.value.map(function(t){return t.toCSS(e)}).join(e.compress?",":", ")}}}(n("../tree")),function(e){e.Variable=function(e,t,n){this.name=e,this.index=t,this.file=n},e.Variable.prototype={eval:function(t){var n,r,i=this.name;i.indexOf("@@")==0&&(i="@"+(new e.Variable(i.slice(1))).eval(t).value);if(n=e.find(t.frames,function(e){if(r=e.variable(i))return r.value.eval(t)}))return n;throw{type:"Name",message:"variable "+i+" is undefined",filename:this.file,index:this.index}}}}(n("../tree")),function(e){e.debugInfo=function(t,n){var r="";if(t.dumpLineNumbers&&!t.compress)switch(t.dumpLineNumbers){case"comments":r=e.debugInfo.asComment(n);break;case"mediaquery":r=e.debugInfo.asMediaQuery(n);break;case"all":r=e.debugInfo.asComment(n)+e.debugInfo.asMediaQuery(n)}return r},e.debugInfo.asComment=function(e){return"/* line "+e.debugInfo.lineNumber+", "+e.debugInfo.fileName+" */\n"},e.debugInfo.asMediaQuery=function(e){return'@media -sass-debug-info{filename{font-family:"'+e.debugInfo.fileName+'";}line{font-family:"'+e.debugInfo.lineNumber+'";}}\n'},e.find=function(e,t){for(var n=0,r;n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var s=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||s?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(s?1e3:1500),r.watch=function(){return this.watchMode=!0},r.unwatch=function(){return this.watchMode=!1};if(r.env==="development"){r.optimization=0,/!watch/.test(location.hash)&&r.watch();var o=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);o&&(r.dumpLineNumbers=o[1]),r.watchTimer=setInterval(function(){r.watchMode&&p(function(e,t,n,r,i){t&&m(t.toCSS(),r,i.lastModified)})},r.poll)}else r.optimization=3;var u;try{u=typeof e.localStorage=="undefined"?null:e.localStorage}catch(a){u=null}var f=document.getElementsByTagName("link"),l=/^text\/(x-)?less$/;r.sheets=[];for(var c=0;c>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof(window) === 'undefined') { - if (typeof(exports) === 'undefined') { - // Rhino - less = {}; - tree = less.tree = {}; - } else { - // Node.js - less = exports, - tree = require('less/tree'); - } -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e) } - - if (c.value && c.value[0] === '&') { - return new(tree.Element)(c, null); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { - i += match[0].length - 1; - selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; - } else { - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page|@-[-a-z]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (typeof(window) !== 'undefined' /* browser */ || typeof(exports) === 'undefined' /* rhino */) { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('less/tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else if (rgb.length == 8) { - this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; - this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - } -}; - - -})(require('less/tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Element = function (combinator, value) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value ? value.trim() : ""; -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('less/tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('less/tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('less/tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('less/tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors( paths, context, this.selectors ); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function( paths, context, selectors ) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function( paths, context, selector ) { - var before = [], after = [], beforeElements = [], afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value[0] === '&') { - hasParentSelector = true; - } - if(!hasParentSelector) { - beforeElements.push(el); - } else { - afterElements.push(el); - } - } - - if(!hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if(beforeElements.length > 0) { - before.push(new (tree.Selector)(beforeElements)); - } - if(afterElements.length > 0) { - after.push(new (tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('less/tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - if (this.elements[0].value === other.elements[0].value) { - return true; - } else { - return false; - } -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('less/tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('less/tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('less/tree')); -require('less/tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('less/tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -var name; - -function loadStyleSheet(sheet, callback, reload, remaining) { - var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; - var input = readFile(sheetName); - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - print("Error: " + e); - quit(1); - } - callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); - }); - - // callback({}, sheet, { local: true, remaining: remaining }); -} - -function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); -} - -// Command line integration via Rhino -(function (args) { - name = args[0]; - var output = args[1]; - - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); - } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - quit(1); - } else { - result = root.toCSS(); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - print("done"); -}(arguments)); diff --git a/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js b/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js deleted file mode 100644 index e755f63..0000000 --- a/enyo/tools/minifier/node_modules/less/dist/less-rhino-1.1.5.js +++ /dev/null @@ -1,2481 +0,0 @@ -// -// Stub out `require` in rhino -// -function require(arg) { - return less[arg.split('/')[1]]; -}; - - -// ecma-5.js -// -// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License -// -- tlrobinson Tom Robinson -// dantman Daniel Friesen - -// -// Array -// -if (!Array.isArray) { - Array.isArray = function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" || - (obj instanceof Array); - }; -} -if (!Array.prototype.forEach) { - Array.prototype.forEach = function(block, thisObject) { - var len = this.length >>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } - } - }; -} -if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - return res; - }; -} -if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } - } - return values; - }; -} -if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; - - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); - - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); - } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; -} -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; - - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; - - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; -} - -// -// Object -// -if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; -} - -// -// String -// -if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; -} -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - less = {}; - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'rhino'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - mime: env && env.mime, // MIME type of .less files - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - that.files[path] = root; // Store the root - - callback(root); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - chunks = []; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - level = 0, - match, - chunk = chunks[0], - inParam, - inString; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = i; - - if (!inString && !inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - if (c === '{' && !inString && !inParam) { level ++; - chunk.push(c); - } else if (c === '}' && !inString && !inParam) { level --; - chunk.push(c); - chunks[++j] = chunk = []; - } else if (c === '(' && !inString && !inParam) { - chunk.push(c); - inParam = true; - } else if (c === ')' && !inString && inParam) { - chunk.push(c); - inParam = false; - } else { - if (c === '"' || c === "'" || c === '`') { - if (! inString) { - inString = c; - } else { - inString = inString === c ? false : inString; - } - } - chunk.push(c); - } - } - if (level > 0) { - throw { - type: 'Syntax', - message: "Missing closing `}`", - filename: env.filename - }; - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = []; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - lines = input.split('\n'); - line = getLine(e.index); - - for (var n = e.index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - throw { - type: e.type, - message: e.message, - filename: env.filename, - index: e.index, - line: typeof(line) === 'number' ? line + 1 : null, - callLine: e.call && (getLine(e.call) + 1), - callExtract: lines[getLine(e.call)], - stack: e.stack, - column: column, - extract: [ - lines[line - 1], - lines[line], - lines[line + 1] - ] - }; - } - if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - - function getLine(index) { - return index ? (input.slice(0, index).match(/\n/g) || "").length : null; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - name: "ParseError", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - if (! $(')')) throw new(Error)("missing closing ) for url()"); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i); - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - $('(') && (args = $(this.entities.arguments)) && $(')'); - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value; - - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - while (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - params.push({ name: param.name, value: value }); - } else { - throw new(Error)("Expected value"); - } - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - if (! $(')')) throw new(Error)("missing closing ) for alpha()"); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (c === ':' && input.charAt(i + 1) === ':') { - i += 2; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)('::'); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path; - if ($(/^@import\s+/) && - (path = $(this.entities.quoted) || $(this.entities.url)) && - $(';')) { - return new(tree.Import)(path, imports); - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import'])) { - return value; - } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (path.charAt(0) !== '/' && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); - }; -} - -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math.round(number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math.round(n); - } else { - throw { - error: "RuntimeError", - message: "math functions take numbers as parameters" - }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index) { - this.name = name; - this.args = args; - this.index = index; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { message: "error evaluating function `" + this.name + "`", - index: this.index }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - this.value = value ? value.trim() : ""; - this.index = index; -}; -tree.Element.prototype.toCSS = function (env) { - return this.combinator.toCSS(env || {}) + this.value; -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '::': '::', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(' '); - } -}; - -})(require('../tree')); -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports) { - var that = this; - - this._path = path; - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (root) { - if (! root) { - throw new(Error)("Error parsing " + that.path); - } - that.root = root; - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function () { - if (this.css) { - return "@import " + this._path.toCSS() + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return ruleset.rules; - } - } -}; - -})(require('../tree')); -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value } -}; - -})(require('../tree')); -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments).rules); - match = true; - } catch (e) { - throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; - } - } - } - if (match) { - return rules; - } else { - throw { message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index }; - } - } - } - throw { message: this.selector.toCSS().trim() + " is undefined", - index: this.index }; - } -}; - -tree.mixin.Definition = function (name, params, rules) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - eval: function (env, args) { - var frame = new(tree.Ruleset)(null, []), context, _arguments = []; - - for (var i = 0, val; i < this.params.length; i++) { - if (this.params[i].name) { - if (val = (args && args[i]) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); - } else { - throw { message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len; - - if (argsLength < this.required) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return v.value || v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Rule = function (name, value, important, index) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + ";"; - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); -(function (tree) { - -tree.Ruleset = function (selectors, rules) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); - - ruleset.root = this.root; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors( paths, context, this.selectors ); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (!/^(?:https?:\/\/|file:\/\/|data:)?/.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); -(function (tree) { - -tree.Variable = function (name, index) { this.name = name, this.index = index }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { message: "variable " + name + " is undefined", - index: this.index }; - } - } -}; - -})(require('../tree')); -require('./tree').find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -require('./tree').jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; -var name; - -function loadStyleSheet(sheet, callback, reload, remaining) { - var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; - var input = readFile(sheetName); - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - print("Error: " + e); - quit(1); - } - callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); - }); - - // callback({}, sheet, { local: true, remaining: remaining }); -} - -function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); -} - -// Command line integration via Rhino -(function (args) { - name = args[0]; - var output = args[1]; - - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); - } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - quit(1); - } else { - result = root.toCSS(); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - print("done"); -}(arguments)); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/browser.js b/enyo/tools/minifier/node_modules/less/lib/less/browser.js deleted file mode 100644 index a9f577f..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/browser.js +++ /dev/null @@ -1,394 +0,0 @@ -// -// browser.js - client-side engine -// - -var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = less.async || false; -less.fileAsync = less.fileAsync || false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); - if (dumpLineNumbers) { - less.dumpLineNumbers = dumpLineNumbers[1]; - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)({ - filename: document.location.href.replace(/#.*$/, ''), - dumpLineNumbers: less.dumpLineNumbers - }).parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var contents = sheet.contents || {}; // Passing a ref to top importing parser content cache trough 'sheet' arg. - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^[a-z-]+:/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - contents[href] = data; // Updating top importing parser content cache - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: href, - 'contents': contents, // Passing top importing parser content cache ref down. - dumpLineNumbers: less.dumpLineNumbers - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - if( sheet.media ){ css.media = sheet.media; } - css.id = id; - var nextEl = sheet && sheet.nextSibling || null; - document.getElementsByTagName('head')[0].insertBefore(css, nextEl); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - try { - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } catch(e) { - //TODO - could do with adding more robust error handling - log('failed to save'); - } - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? less.fileAsync : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol && !less.fileAsync) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - var filenameNoPath = filename.match(/([^\/]+)$/)[1]; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filenameNoPath + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - '
      ' + error.join('') + '
    '; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - diff --git a/enyo/tools/minifier/node_modules/less/lib/less/colors.js b/enyo/tools/minifier/node_modules/less/lib/less/colors.js deleted file mode 100644 index b417af6..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/colors.js +++ /dev/null @@ -1,152 +0,0 @@ -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - // 'transparent':'rgba(0,0,0,0)', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js b/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js deleted file mode 100644 index 427de71..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/cssmin.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * cssmin.js - * Author: Stoyan Stefanov - http://phpied.com/ - * This is a JavaScript port of the CSS minification tool - * distributed with YUICompressor, itself a port - * of the cssmin utility by Isaac Schlueter - http://foohack.com/ - * Permission is hereby granted to use the JavaScript version under the same - * conditions as the YUICompressor (original YUICompressor note below). - */ - -/* -* YUI Compressor -* http://developer.yahoo.com/yui/compressor/ -* Author: Julien Lecomte - http://www.julienlecomte.net/ -* Copyright (c) 2011 Yahoo! Inc. All rights reserved. -* The copyrights embodied in the content of this file are licensed -* by Yahoo! Inc. under the BSD (revised) open source license. -*/ -var YAHOO = YAHOO || {}; -YAHOO.compressor = YAHOO.compressor || {}; - -/** - * Utility method to replace all data urls with tokens before we start - * compressing, to avoid performance issues running some of the subsequent - * regexes against large strings chunks. - * - * @private - * @method _extractDataUrls - * @param {String} css The input css - * @param {Array} The global array of tokens to preserve - * @returns String The processed css - */ -YAHOO.compressor._extractDataUrls = function (css, preservedTokens) { - - // Leave data urls alone to increase parse performance. - var maxIndex = css.length - 1, - appendIndex = 0, - startIndex, - endIndex, - terminator, - foundTerminator, - sb = [], - m, - preserver, - token, - pattern = /url\(\s*(["']?)data\:/g; - - // Since we need to account for non-base64 data urls, we need to handle - // ' and ) being part of the data string. Hence switching to indexOf, - // to determine whether or not we have matching string terminators and - // handling sb appends directly, instead of using matcher.append* methods. - - while ((m = pattern.exec(css)) !== null) { - - startIndex = m.index + 4; // "url(".length() - terminator = m[1]; // ', " or empty (not quoted) - - if (terminator.length === 0) { - terminator = ")"; - } - - foundTerminator = false; - - endIndex = pattern.lastIndex - 1; - - while(foundTerminator === false && endIndex+1 <= maxIndex) { - endIndex = css.indexOf(terminator, endIndex + 1); - - // endIndex == 0 doesn't really apply here - if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) { - foundTerminator = true; - if (")" != terminator) { - endIndex = css.indexOf(")", endIndex); - } - } - } - - // Enough searching, start moving stuff over to the buffer - sb.push(css.substring(appendIndex, m.index)); - - if (foundTerminator) { - token = css.substring(startIndex, endIndex); - token = token.replace(/\s+/g, ""); - preservedTokens.push(token); - - preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)"; - sb.push(preserver); - - appendIndex = endIndex + 1; - } else { - // No end terminator found, re-add the whole match. Should we throw/warn here? - sb.push(css.substring(m.index, pattern.lastIndex)); - appendIndex = pattern.lastIndex; - } - } - - sb.push(css.substring(appendIndex)); - - return sb.join(""); -}; - -/** - * Utility method to compress hex color values of the form #AABBCC to #ABC. - * - * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). - * e.g. #AddressForm { ... } - * - * DOES NOT compress IE filters, which have hex color values (which would break things). - * e.g. filter: chroma(color="#FFFFFF"); - * - * DOES NOT compress invalid hex values. - * e.g. background-color: #aabbccdd - * - * @private - * @method _compressHexColors - * @param {String} css The input css - * @returns String The processed css - */ -YAHOO.compressor._compressHexColors = function(css) { - - // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) - var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi, - m, - index = 0, - isFilter, - sb = []; - - while ((m = pattern.exec(css)) !== null) { - - sb.push(css.substring(index, m.index)); - - isFilter = m[1]; - - if (isFilter) { - // Restore, maintain case, otherwise filter will break - sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7])); - } else { - if (m[2].toLowerCase() == m[3].toLowerCase() && - m[4].toLowerCase() == m[5].toLowerCase() && - m[6].toLowerCase() == m[7].toLowerCase()) { - - // Compress. - sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase()); - } else { - // Non compressible color, restore but lower case. - sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase()); - } - } - - index = pattern.lastIndex = pattern.lastIndex - m[8].length; - } - - sb.push(css.substring(index)); - - return sb.join(""); -}; - -YAHOO.compressor.cssmin = function (css, linebreakpos) { - - var startIndex = 0, - endIndex = 0, - i = 0, max = 0, - preservedTokens = [], - comments = [], - token = '', - totallen = css.length, - placeholder = ''; - - css = this._extractDataUrls(css, preservedTokens); - - // collect all comment blocks... - while ((startIndex = css.indexOf("/*", startIndex)) >= 0) { - endIndex = css.indexOf("*/", startIndex + 2); - if (endIndex < 0) { - endIndex = totallen; - } - token = css.slice(startIndex + 2, endIndex); - comments.push(token); - css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex); - startIndex += 2; - } - - // preserve strings so their content doesn't get accidentally minified - css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) { - var i, max, quote = match.substring(0, 1); - - match = match.slice(1, -1); - - // maybe the string contains a comment-like substring? - // one, maybe more? put'em back then - if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { - for (i = 0, max = comments.length; i < max; i = i + 1) { - match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]); - } - } - - // minify alpha opacity in filter strings - match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - preservedTokens.push(match); - return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote; - }); - - // strings are safe, now wrestle the comments - for (i = 0, max = comments.length; i < max; i = i + 1) { - - token = comments[i]; - placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; - - // ! in the first position of the comment means preserve - // so push to the preserved tokens keeping the ! - if (token.charAt(0) === "!") { - preservedTokens.push(token); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // \ in the last position looks like hack for Mac/IE5 - // shorten that to /*\*/ and the next one to /**/ - if (token.charAt(token.length - 1) === "\\") { - preservedTokens.push("\\"); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - i = i + 1; // attn: advancing the loop - preservedTokens.push(""); - css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // keep empty comments after child selectors (IE7 hack) - // e.g. html >/**/ body - if (token.length === 0) { - startIndex = css.indexOf(placeholder); - if (startIndex > 2) { - if (css.charAt(startIndex - 3) === '>') { - preservedTokens.push(""); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - } - } - } - - // in all other cases kill the comment - css = css.replace("/*" + placeholder + "*/", ""); - } - - - // Normalize all whitespace strings to single spaces. Easier to work with that way. - css = css.replace(/\s+/g, " "); - - // Remove the spaces before the things that should not have spaces before them. - // But, be careful not to turn "p :link {...}" into "p:link{...}" - // Swap out any pseudo-class colons with the token, and then swap back. - css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) { - return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___"); - }); - css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1'); - css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":"); - - // retain space for special IE6 cases - css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2"); - - // no space after the end of a preserved comment - css = css.replace(/\*\/ /g, '*/'); - - - // If there is a @charset, then only allow one, and push to the top of the file. - css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1'); - css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1'); - - // Put the space back in some cases, to support stuff like - // @media screen and (-webkit-min-device-pixel-ratio:0){ - css = css.replace(/\band\(/gi, "and ("); - - - // Remove the spaces after the things that should not have spaces after them. - css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1'); - - // remove unnecessary semicolons - css = css.replace(/;+\}/g, "}"); - - // Replace 0(px,em,%) with 0. - css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2"); - - // Replace 0 0 0 0; with 0. - css = css.replace(/:0 0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0(;|\})/g, ":0$1"); - - // Replace background-position:0; with background-position:0 0; - // same for transform-origin - css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0 0" + tail; - }); - - // Replace 0.6 to .6, but only when preceded by : or a white-space - css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2"); - - // Shorten colors from rgb(51,102,153) to #336699 - // This makes it more likely that it'll get further compressed in the next step. - css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () { - var i, rgbcolors = arguments[1].split(','); - for (i = 0; i < rgbcolors.length; i = i + 1) { - rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16); - if (rgbcolors[i].length === 1) { - rgbcolors[i] = '0' + rgbcolors[i]; - } - } - return '#' + rgbcolors.join(''); - }); - - // Shorten colors from #AABBCC to #ABC. - css = this._compressHexColors(css); - - // border: none -> border:0 - css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0" + tail; - }); - - // shorter opacity IE filter - css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - // Remove empty rules. - css = css.replace(/[^\};\{\/]+\{\}/g, ""); - - if (linebreakpos >= 0) { - // Some source control tools don't like it when files containing lines longer - // than, say 8000 characters, are checked in. The linebreak option is used in - // that case to split long lines after a specific column. - startIndex = 0; - i = 0; - while (i < css.length) { - i = i + 1; - if (css[i - 1] === '}' && i - startIndex > linebreakpos) { - css = css.slice(0, i) + '\n' + css.slice(i); - startIndex = i; - } - } - } - - // Replace multiple semi-colons in a row by a single one - // See SF bug #1980989 - css = css.replace(/;;+/g, ";"); - - // restore preserved comments and strings - for (i = 0, max = preservedTokens.length; i < max; i = i + 1) { - css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]); - } - - // Trim the final string (for any leading or trailing white spaces) - css = css.replace(/^\s+|\s+$/g, ""); - - return css; - -}; - -exports.compressor = YAHOO.compressor; diff --git a/enyo/tools/minifier/node_modules/less/lib/less/functions.js b/enyo/tools/minifier/node_modules/less/lib/less/functions.js deleted file mode 100644 index 2e0cc51..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/functions.js +++ /dev/null @@ -1,337 +0,0 @@ -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - red: function (color) { - return new(tree.Dimension)(color.rgb[0]); - }, - green: function (color) { - return new(tree.Dimension)(color.rgb[1]); - }, - blue: function (color) { - return new(tree.Dimension)(color.rgb[2]); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - luma: function (color) { - return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + - 0.7152 * (color.rgb[1]/255) + - 0.0722 * (color.rgb[2]/255)) - * color.alpha * 100), '%'); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - if (!weight) { - weight = new(tree.Dimension)(50); - } - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - contrast: function (color, dark, light, threshold) { - if (typeof light === 'undefined') { - light = this.rgba(255, 255, 255, 1.0); - } - if (typeof dark === 'undefined') { - dark = this.rgba(0, 0, 0, 1.0); - } - if (typeof threshold === 'undefined') { - threshold = 0.43; - } else { - threshold = threshold.value; - } - if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { - return light; - } else { - return dark; - } - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n, f) { - var fraction = typeof(f) === "undefined" ? 0 : f.value; - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); - } else if (typeof(n) === 'number') { - return n.toFixed(fraction); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - }, - - /* Blending modes */ - - multiply: function(color1, color2) { - var r = color1.rgb[0] * color2.rgb[0] / 255; - var g = color1.rgb[1] * color2.rgb[1] / 255; - var b = color1.rgb[2] * color2.rgb[2] / 255; - return this.rgb(r, g, b); - }, - screen: function(color1, color2) { - var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; - var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; - var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - overlay: function(color1, color2) { - var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; - var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; - var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - softlight: function(color1, color2) { - var t = color2.rgb[0] * color1.rgb[0] / 255; - var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; - t = color2.rgb[1] * color1.rgb[1] / 255; - var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; - t = color2.rgb[2] * color1.rgb[2] / 255; - var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; - return this.rgb(r, g, b); - }, - hardlight: function(color1, color2) { - var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; - var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; - var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - difference: function(color1, color2) { - var r = Math.abs(color1.rgb[0] - color2.rgb[0]); - var g = Math.abs(color1.rgb[1] - color2.rgb[1]); - var b = Math.abs(color1.rgb[2] - color2.rgb[2]); - return this.rgb(r, g, b); - }, - exclusion: function(color1, color2) { - var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; - var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; - var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; - return this.rgb(r, g, b); - }, - average: function(color1, color2) { - var r = (color1.rgb[0] + color2.rgb[0]) / 2; - var g = (color1.rgb[1] + color2.rgb[1]) / 2; - var b = (color1.rgb[2] + color2.rgb[2]) / 2; - return this.rgb(r, g, b); - }, - negation: function(color1, color2) { - var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); - var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); - var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); - return this.rgb(r, g, b); - }, - tint: function(color, amount) { - return this.mix(this.rgb(255,255,255), color, amount); - }, - shade: function(color, amount) { - return this.mix(this.rgb(0, 0, 0), color, amount); - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/index.js b/enyo/tools/minifier/node_modules/less/lib/less/index.js deleted file mode 100644 index 7ffbbcf..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/index.js +++ /dev/null @@ -1,140 +0,0 @@ -var path = require('path'), - sys = require('util'), - fs = require('fs'); - -var less = { - version: [1, 3, 0], - Parser: require('./parser').Parser, - importer: require('./parser').importer, - tree: require('./tree'), - render: function (input, options, callback) { - options = options || {}; - - if (typeof(options) === 'function') { - callback = options, options = {}; - } - - var parser = new(less.Parser)(options), - ee; - - if (callback) { - parser.parse(input, function (e, root) { - callback(e, root && root.toCSS && root.toCSS(options)); - }); - } else { - ee = new(require('events').EventEmitter); - - process.nextTick(function () { - parser.parse(input, function (e, root) { - if (e) { ee.emit('error', e) } - else { ee.emit('success', root.toCSS(options)) } - }); - }); - return ee; - } - }, - formatError: function(ctx, options) { - options = options || {}; - - var message = ""; - var extract = ctx.extract; - var error = []; - var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str }; - - if (ctx.stack) { return stylize(ctx.stack, 'red') } - - if (!ctx.hasOwnProperty('index')) { - return ctx.stack || ctx.message; - } - - if (typeof(extract[0]) === 'string') { - error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); - } - - if (extract[1]) { - error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) - + stylize(stylize(stylize(extract[1][ctx.column], 'bold') - + extract[1].slice(ctx.column + 1), 'red'), 'inverse')); - } - - if (typeof(extract[2]) === 'string') { - error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); - } - error = error.join('\n') + stylize('', 'reset') + '\n'; - - message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); - ctx.filename && (message += stylize(' in ', 'red') + ctx.filename + - stylize(':' + ctx.line + ':' + ctx.column, 'grey')); - - message += '\n' + error; - - if (ctx.callLine) { - message += stylize('from ', 'red') + (ctx.filename || '') + '/n'; - message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n'; - } - - return message; - }, - writeError: function (ctx, options) { - options = options || {}; - if (options.silent) { return } - sys.error(less.formatError(ctx, options)); - } -}; - -['color', 'directive', 'operation', 'dimension', - 'keyword', 'variable', 'ruleset', 'element', - 'selector', 'quoted', 'expression', 'rule', - 'call', 'url', 'alpha', 'import', - 'mixin', 'comment', 'anonymous', 'value', - 'javascript', 'assignment', 'condition', 'paren', - 'media', 'ratio' -].forEach(function (n) { - require('./tree/' + n); -}); - -less.Parser.importer = function (file, paths, callback, env) { - var pathname; - - // TODO: Undo this at some point, - // or use different approach. - var paths = [].concat(paths); // Avoid passing paths by reference down the import tree... - paths.unshift('.'); // ...which results on a lot of repeated '.' paths. - - for (var i = 0; i < paths.length; i++) { - try { - pathname = path.join(paths[i], file); - fs.statSync(pathname); - break; - } catch (e) { - pathname = null; - } - } - - if (pathname) { - fs.readFile(pathname, 'utf-8', function(e, data) { - if (e) return callback(e); - - env.contents[pathname] = data; // Updating top importing parser content cache. - new(less.Parser)({ - paths: [path.dirname(pathname)].concat(paths), - filename: pathname, - contents: env.contents, - dumpLineNumbers: env.dumpLineNumbers - }).parse(data, function (e, root) { - callback(e, root); - }); - }); - } else { - if (typeof(env.errback) === "function") { - env.errback(file, paths, callback); - } else { - callback({ type: 'File', message: "'" + file + "' wasn't found.\n" }); - } - } -} - -require('./functions'); -require('./colors'); - -for (var k in less) { exports[k] = less[k] } diff --git a/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js b/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js deleted file mode 100644 index 7c051be..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/lessc_helper.js +++ /dev/null @@ -1,59 +0,0 @@ -// lessc_helper.js -// -// helper functions for lessc -sys = require('util'); - -var lessc_helper = { - - //Stylize a string - stylize : function(str, style) { - var styles = { - 'reset' : [0, 0], - 'bold' : [1, 22], - 'inverse' : [7, 27], - 'underline' : [4, 24], - 'yellow' : [33, 39], - 'green' : [32, 39], - 'red' : [31, 39], - 'grey' : [90, 39] - }; - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; - }, - - //Print command line options - printUsage: function() { - sys.puts("usage: lessc [options] [destination]"); - sys.puts(""); - sys.puts("If source is set to `-' (dash or hyphen-minus), input is read from stdin."); - sys.puts(""); - sys.puts("options:"); - sys.puts(" -h, --help Print help (this message) and exit."); - sys.puts(" --include-path Set include paths. Separated by `:'. Use `;' on Windows."); - sys.puts(" --no-color Disable colorized output."); - sys.puts(" -s, --silent Suppress output of error messages."); - sys.puts(" --strict-imports Force evaluation of imports."); - sys.puts(" --verbose Be verbose."); - sys.puts(" -v, --version Print version number and exit."); - sys.puts(" -x, --compress Compress output by removing some whitespaces."); - sys.puts(" --yui-compress Compress output using cssmin.js."); - sys.puts(" -O0, -O1, -O2 Set the parser's optimization level. The lower"); - sys.puts(" the number, the less nodes it will create in the"); - sys.puts(" tree. This could matter for debugging, or if you"); - sys.puts(" want to access the individual nodes in the tree."); - sys.puts(" --line-numbers=TYPE Outputs filename and line numbers."); - sys.puts(" TYPE can be either 'comments', which will output"); - sys.puts(" the debug info within comments, 'mediaquery'"); - sys.puts(" that will output the information within a fake"); - sys.puts(" media query which is compatible with the SASS"); - sys.puts(" format, and 'all' which will do both."); - sys.puts(""); - sys.puts("Report bugs to: http://github.com/cloudhead/less.js/issues"); - sys.puts("Home page: "); - } - - -} - -// Exports helper functions -for (var h in lessc_helper) { exports[h] = lessc_helper[h] } diff --git a/enyo/tools/minifier/node_modules/less/lib/less/parser.js b/enyo/tools/minifier/node_modules/less/lib/less/parser.js deleted file mode 100644 index 6bb90cd..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/parser.js +++ /dev/null @@ -1,1445 +0,0 @@ -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // Top parser on an import tree must be sure there is one "env" - // which will then be passed arround by reference. - var env = env || { }; - if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: env.contents, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - - var imported = path in that.files; - - that.files[path] = root; // Store the root - - if (e && !that.error) { that.error = e } - - callback(e, root, imported); - - if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - function isWhitespace(c) { - // Could change to \s? - var code = c.charCodeAt(0); - return code === 32 || code === 10 || code === 9; - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, index, k; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - skipWhitespace(length); - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function skipWhitespace(length) { - var oldi = i, oldj = j, - endIndex = i + chunks[j].length, - mem = i += length; - - while (i < endIndex) { - if (! isWhitespace(input.charAt(i))) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - return oldi !== i || oldj !== j; - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[e.filename]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function getFileName(e) { - if(less.mode === 'browser' || less.mode === 'rhino') - return e.filename; - else - return require('path').resolve(e.filename); - } - - function getDebugInfo(index, inputStream, e) { - return { - lineNumber: getLocation(index, inputStream).line + 1, - fileName: getFileName(e) - }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Remove potential UTF Byte Order Mark - input = input.replace(/^\uFEFF/, ''); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function (e) { - if (e) callback(e); - else callback(null, root); - }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, nameLC, args, alpha_ret, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1]; - nameLC = name.toLowerCase(); - - if (nameLC === 'url') { return null } - else { i += name.length } - - if (nameLC === 'alpha') { - alpha_ret = $(this.alpha); - if(typeof alpha_ret !== 'undefined') { - return alpha_ret; - } - } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.ratio) || - $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value != null || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // A variable entity useing the protective {} e.g. @{var} - variableCurly: function () { - var name, curly, index = i; - - if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { - return new(tree.Variable)("@" + curly[1], index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // A Ratio - // - // 16/9 - // - ratio: function () { - var value, c = input.charCodeAt(i); - if (c > 57 || c < 48) return; - - if (value = $(/^(\d+\/\d+)/)) { - return new(tree.Ratio)(value[1]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - save(); - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - - restore(); - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; - - if (s !== '.' && s !== '#') { return } - - save(); // stop us absorbing part of an invalid selector - - while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - if ($('(')) { - while (arg = $(this.expression)) { - value = arg; - name = null; - - // Variable - if (arg.value.length == 1) { - var val = arg.value[0]; - if (val instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - name = val.name; - } else { - throw new(Error)("Expected value"); - } - } - } - } - - args.push({ name: name, value: value }); - - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - } - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - - restore(); - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - // .mixincall("@{a}"); - // looks a bit like a mixin definition.. so we have to be nice and restore - if (!$(')')) { - furthest = i; - restore(); - } - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || - $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); - - if (! e) { - if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { - e = new(tree.Paren)(v); - } - } - - if (e) { return new(tree.Element)(c, e, i) } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i).match(/\s/)) { i++ } - return new(tree.Combinator)(c); - } else if (input.charAt(i - 1).match(/\s/)) { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - // depreciated, will be removed soon - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); - } - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match, debugInfo; - save(); - - if (env.dumpLineNumbers) - debugInfo = getDebugInfo(i, input, env); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); - if (env.dumpLineNumbers) - ruleset.debugInfo = debugInfo; - return ruleset; - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - - save(); - - var dir = $(/^@import(?:-(once))?\s+/); - - if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); - } - } - - restore(); - }, - - mediaFeature: function () { - var e, p, nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules, media, debugInfo; - - if (env.dumpLineNumbers) - debugInfo = getDebugInfo(i, input, env); - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - media = new(tree.Media)(rules, features); - if(env.dumpLineNumbers) - media.debugInfo = debugInfo; - return media; - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, identifier, e, nodes, nonVendorSpecificName, - hasBlock, hasIdentifier; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } - - save(); - - name = $(/^@[a-z-]+/); - - nonVendorSpecificName = name; - if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { - nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); - } - - switch(nonVendorSpecificName) { - case "@font-face": - hasBlock = true; - break; - case "@viewport": - case "@top-left": - case "@top-left-corner": - case "@top-center": - case "@top-right": - case "@top-right-corner": - case "@bottom-left": - case "@bottom-left-corner": - case "@bottom-center": - case "@bottom-right": - case "@bottom-right-corner": - case "@left-top": - case "@left-middle": - case "@left-bottom": - case "@right-top": - case "@right-middle": - case "@right-bottom": - hasBlock = true; - break; - case "@page": - case "@document": - case "@supports": - case "@keyframes": - hasBlock = true; - hasIdentifier = true; - break; - } - - if (hasIdentifier) { - name += " " + ($(/^[^{]+/) || '').trim(); - } - - if (hasBlock) - { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else { - if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - - restore(); - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ - loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - diff --git a/enyo/tools/minifier/node_modules/less/lib/less/rhino.js b/enyo/tools/minifier/node_modules/less/lib/less/rhino.js deleted file mode 100644 index 9bfe8f4..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/rhino.js +++ /dev/null @@ -1,123 +0,0 @@ -var name; - -function loadStyleSheet(sheet, callback, reload, remaining) { - var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), - sheetName = name.slice(0, endOfPath + 1) + sheet.href, - contents = sheet.contents || {}, - input = readFile(sheetName); - - contents[sheetName] = input; - - var parser = new less.Parser({ - paths: [sheet.href.replace(/[\w\.-]+$/, '')], - contents: contents - }); - parser.parse(input, function (e, root) { - if (e) { - return error(e, sheetName); - } - try { - callback(e, root, sheet, { local: false, lastModified: 0, remaining: remaining }); - } catch(e) { - error(e, sheetName); - } - }); -} - -function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); -} - -// Command line integration via Rhino -(function (args) { - var output, - compress = false, - i; - - for(i = 0; i < args.length; i++) { - switch(args[i]) { - case "-x": - compress = true; - break; - default: - if (!name) { - name = args[i]; - } else if (!output) { - output = args[i]; - } else { - print("unrecognised parameters"); - print("input_file [output_file] [-x]"); - } - } - } - - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); - } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - try { - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - error(e, name); - quit(1); - } else { - result = root.toCSS({compress: compress || false}); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - } - catch(e) { - error(e, name); - quit(1); - } - print("done"); -}(arguments)); - -function error(e, filename) { - - var content = "Error : " + filename + "\n"; - - filename = e.filename || filename; - - if (e.message) { - content += e.message + "\n"; - } - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - content += - String(parseInt(e.line) + (i - 1)) + - ":" + e.extract[i] + "\n"; - } - }; - - if (e.stack) { - content += e.stack; - } else if (e.extract) { - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; - errorline(e, 0); - errorline(e, 1); - errorline(e, 2); - } - print(content); -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree.js b/enyo/tools/minifier/node_modules/less/lib/less/tree.js deleted file mode 100644 index 7038ecc..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree.js +++ /dev/null @@ -1,43 +0,0 @@ -(function (tree) { - -tree.debugInfo = function(env, ctx) { - var result=""; - if (env.dumpLineNumbers && !env.compress) { - switch(env.dumpLineNumbers) { - case 'comments': - result = tree.debugInfo.asComment(ctx); - break; - case 'mediaquery': - result = tree.debugInfo.asMediaQuery(ctx); - break; - case 'all': - result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); - break; - } - } - return result; -}; - -tree.debugInfo.asComment = function(ctx) { - return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; -}; - -tree.debugInfo.asMediaQuery = function(ctx) { - return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; -}; - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js deleted file mode 100644 index 139ae92..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/alpha.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js deleted file mode 100644 index 4461490..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/anonymous.js +++ /dev/null @@ -1,27 +0,0 @@ -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this }, - compare: function (x) { - if (!x.toCSS) { - return -1; - } - - var left = this.toCSS(), - right = x.toCSS(); - - if (left === right) { - return 0; - } - - return left < right ? -1 : 1; - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js deleted file mode 100644 index a5559ad..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/assignment.js +++ /dev/null @@ -1,19 +0,0 @@ -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { - return new(tree.Assignment)(this.key, this.value.eval(env)); - } - return this; - } -}; - -})(require('../tree')); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js deleted file mode 100644 index 7c2d21e..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/call.js +++ /dev/null @@ -1,48 +0,0 @@ -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js deleted file mode 100644 index 6adf317..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/color.js +++ /dev/null @@ -1,111 +0,0 @@ -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - }, - compare: function (x) { - if (!x.rgb) { - return -1; - } - - return (x.rgb[0] === this.rgb[0] && - x.rgb[1] === this.rgb[1] && - x.rgb[2] === this.rgb[2] && - x.alpha === this.alpha) ? 0 : -1; - } -}; - - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js deleted file mode 100644 index f4a3384..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/comment.js +++ /dev/null @@ -1,14 +0,0 @@ -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js deleted file mode 100644 index 6b79dc9..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/condition.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js deleted file mode 100644 index 9a6fce3..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/dimension.js +++ /dev/null @@ -1,49 +0,0 @@ -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js deleted file mode 100644 index 4d682e6..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/directive.js +++ /dev/null @@ -1,39 +0,0 @@ -(function (tree) { - -tree.Directive = function (name, value) { - this.name = name; - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - var evaldDirective = this; - if (this.ruleset) { - env.frames.unshift(this); - evaldDirective = new(tree.Directive)(this.name); - evaldDirective.ruleset = this.ruleset.eval(env); - env.frames.shift(); - } - return evaldDirective; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js deleted file mode 100644 index f02b5ab..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/element.js +++ /dev/null @@ -1,48 +0,0 @@ -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); - if (value == '' && this.combinator.value.charAt(0) == '&') { - return ''; - } else { - return this.combinator.toCSS(env || {}) + value; - } -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js deleted file mode 100644 index fbfa9c5..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/expression.js +++ /dev/null @@ -1,23 +0,0 @@ -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js deleted file mode 100644 index 7a977de..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/import.js +++ /dev/null @@ -1,83 +0,0 @@ -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, once, index) { - var that = this; - - this.once = once; - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root, imported) { - if (e) { e.index = index } - if (imported && that.once) that.skip = imported; - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.skip) return []; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js deleted file mode 100644 index 772a31d..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/javascript.js +++ /dev/null @@ -1,51 +0,0 @@ -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js deleted file mode 100644 index 701b79e..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/keyword.js +++ /dev/null @@ -1,19 +0,0 @@ -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js deleted file mode 100644 index 3bc4c54..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/media.js +++ /dev/null @@ -1,123 +0,0 @@ -(function (tree) { - -tree.Media = function (value, features) { - var selectors = this.emptySelectors(); - - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; -}; -tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); - - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - if(this.debugInfo) { - this.ruleset.debugInfo = this.debugInfo; - media.debugInfo = this.debugInfo; - } - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - emptySelectors: function() { - var el = new(tree.Element)('', '&', 0); - return [new(tree.Selector)([el])]; - }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var selectors = this.emptySelectors(); - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; - } - }, - bubbleSelectors: function (selectors) { - this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js deleted file mode 100644 index b441bf3..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/mixin.js +++ /dev/null @@ -1,146 +0,0 @@ -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { - return { name: a.name, value: a.value.eval(env) }; - }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs, arg; - - for (var i = 0, val, name; i < this.params.length; i++) { - arg = args && args[i] - - if (arg && arg.name) { - frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); - args.splice(i, 1); - i--; - continue; - } - - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].value.eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (arg && arg.value) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push((args[i] && args[i].value) || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - } - - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js deleted file mode 100644 index 1ce22fb..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/operation.js +++ /dev/null @@ -1,32 +0,0 @@ -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js deleted file mode 100644 index 384a43c..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/paren.js +++ /dev/null @@ -1,16 +0,0 @@ - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js deleted file mode 100644 index f93dc8e..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/quoted.js +++ /dev/null @@ -1,43 +0,0 @@ -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - }, - compare: function (x) { - if (!x.toCSS) { - return -1; - } - - var left = this.toCSS(), - right = x.toCSS(); - - if (left === right) { - return 0; - } - - return left < right ? -1 : 1; - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js deleted file mode 100644 index f7622fb..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/ratio.js +++ /dev/null @@ -1,13 +0,0 @@ -(function (tree) { - -tree.Ratio = function (value) { - this.value = value; -}; -tree.Ratio.prototype = { - toCSS: function (env) { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js deleted file mode 100644 index 9e4e54a..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/rule.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js deleted file mode 100644 index 822f331..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/ruleset.js +++ /dev/null @@ -1,374 +0,0 @@ -(function (tree) { - -tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - var rules = []; - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - if(this.debugInfo) { - ruleset.debugInfo = this.debugInfo; - } - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - rules = rules.concat(ruleset.rules[i].eval(env)); - } else { - rules.push(ruleset.rules[i]); - } - } - ruleset.rules = rules; - rules = []; - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - rules = rules.concat(ruleset.rules[i].eval(env)); - } else { - rules.push(ruleset.rules[i]); - } - } - ruleset.rules = rules; - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - if (env.mediaBlocks) { - for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { - env.mediaBlocks[i].bubbleSelectors(selectors); - } - } - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - _rules = [], // - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - debugInfo, // Line number debugging - rule; - - if (! this.root) { - this.joinSelectors(paths, context, this.selectors); - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - debugInfo = tree.debugInfo(env, this); - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : ',\n'); - - // Remove duplicates - for (var i = rules.length - 1; i >= 0; i--) { - if (_rules.indexOf(rules[i]) === -1) { - _rules.unshift(rules[i]); - } - } - rules = _rules; - - css.push(debugInfo + selector + - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - - var i, j, k, - hasParentSelector, newSelectors, el, sel, parentSel, - newSelectorPath, afterParentJoin, newJoinedSelector, - newJoinedSelectorEmpty, lastSelector, currentElements, - selectorsMultiplied; - - for (i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.value === '&') { - hasParentSelector = true; - } - } - - if (!hasParentSelector) { - if (context.length > 0) { - for(i = 0; i < context.length; i++) { - paths.push(context[i].concat(selector)); - } - } - else { - paths.push([selector]); - } - return; - } - - // The paths are [[Selector]] - // The first list is a list of comma seperated selectors - // The inner list is a list of inheritance seperated selectors - // e.g. - // .a, .b { - // .c { - // } - // } - // == [[.a] [.c]] [[.b] [.c]] - // - - // the elements from the current selector so far - currentElements = []; - // the current list of new selectors to add to the path. - // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors - // by the parents - newSelectors = [[]]; - - for (i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - // non parent reference elements just get added - if (el.value !== "&") { - currentElements.push(el); - } else { - // the new list of selectors to add - selectorsMultiplied = []; - - // merge the current list of non parent selector elements - // on to the current list of selectors to add - if (currentElements.length > 0) { - this.mergeElementsOnToSelectors(currentElements, newSelectors); - } - - // loop through our current selectors - for(j = 0; j < newSelectors.length; j++) { - sel = newSelectors[j]; - // if we don't have any parent paths, the & might be in a mixin so that it can be used - // whether there are parents or not - if (context.length == 0) { - // the combinator used on el should now be applied to the next element instead so that - // it is not lost - if (sel.length > 0) { - sel[0].elements = sel[0].elements.slice(0); - sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); - } - selectorsMultiplied.push(sel); - } - else { - // and the parent selectors - for(k = 0; k < context.length; k++) { - parentSel = context[k]; - // We need to put the current selectors - // then join the last selector's elements on to the parents selectors - - // our new selector path - newSelectorPath = []; - // selectors from the parent after the join - afterParentJoin = []; - newJoinedSelectorEmpty = true; - - //construct the joined selector - if & is the first thing this will be empty, - // if not newJoinedSelector will be the last set of elements in the selector - if (sel.length > 0) { - newSelectorPath = sel.slice(0); - lastSelector = newSelectorPath.pop(); - newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); - newJoinedSelectorEmpty = false; - } - else { - newJoinedSelector = new(tree.Selector)([]); - } - - //put together the parent selectors after the join - if (parentSel.length > 1) { - afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); - } - - if (parentSel.length > 0) { - newJoinedSelectorEmpty = false; - - // join the elements so far with the first part of the parent - newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); - newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); - } - - if (!newJoinedSelectorEmpty) { - // now add the joined selector - newSelectorPath.push(newJoinedSelector); - } - - // and the rest of the parent - newSelectorPath = newSelectorPath.concat(afterParentJoin); - - // add that to our new set of selectors - selectorsMultiplied.push(newSelectorPath); - } - } - } - - // our new selectors has been multiplied, so reset the state - newSelectors = selectorsMultiplied; - currentElements = []; - } - } - - // if we have any elements left over (e.g. .a& .b == .b) - // add them on to all the current selectors - if (currentElements.length > 0) { - this.mergeElementsOnToSelectors(currentElements, newSelectors); - } - - for(i = 0; i < newSelectors.length; i++) { - paths.push(newSelectors[i]); - } - }, - - mergeElementsOnToSelectors: function(elements, selectors) { - var i, sel; - - if (selectors.length == 0) { - selectors.push([ new(tree.Selector)(elements) ]); - return; - } - - for(i = 0; i < selectors.length; i++) { - sel = selectors[i]; - - // if the previous thing in sel is a parent this needs to join on to it - if (sel.length > 0) { - sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); - } - else { - sel.push(new(tree.Selector)(elements)); - } - } - } -}; -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js deleted file mode 100644 index 469629c..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/selector.js +++ /dev/null @@ -1,47 +0,0 @@ -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - if (this.elements[0].combinator.value === "") { - this._css = ' '; - } else { - this._css = ''; - } - - this._css += this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); - - return this._css; -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js deleted file mode 100644 index e755594..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/url.js +++ /dev/null @@ -1,29 +0,0 @@ -(function (tree) { - -tree.URL = function (val, paths) { - this.value = val; - this.paths = paths; -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + this.value.toCSS() + ")"; - }, - eval: function (ctx) { - var val = this.value.eval(ctx); - - // Add the base path if the URL is relative and we are either - // a.) in the browser or - // b.) we have a relative file URL - if ((this.paths.length > 0) && - (typeof window !== 'undefined' || !/^(?:[A-Za-z-]+:|\/)/.test(this.paths[0])) && - (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value))) { - var path = this.paths[0].slice(-1) === '/' ? this.paths[0] : this.paths[0] + '/'; - var v = path + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - val = new(tree.Anonymous)(v); - } - - return new(tree.URL)(val, this.paths); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js deleted file mode 100644 index 3c1eb29..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/value.js +++ /dev/null @@ -1,24 +0,0 @@ -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js b/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js deleted file mode 100644 index ee557e1..0000000 --- a/enyo/tools/minifier/node_modules/less/lib/less/tree/variable.js +++ /dev/null @@ -1,26 +0,0 @@ -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); diff --git a/enyo/tools/minifier/node_modules/less/package.json b/enyo/tools/minifier/node_modules/less/package.json deleted file mode 100644 index 7930402..0000000 --- a/enyo/tools/minifier/node_modules/less/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name" : "less", - "description" : "Leaner CSS", - "url" : "http://lesscss.org", - "keywords" : ["css", "parser", "lesscss", "browser"], - "author" : "Alexis Sellier ", - "contributors" : [], - "version" : "1.3.0", - "bin" : { "lessc": "./bin/lessc" }, - "main" : "./lib/less/index", - "directories" : { "test": "./test" }, - "engines" : { "node": ">=0.4.0" }, - "devDependencies" : { "diff": "~1.0.2" }, - "scripts": { - "test": "make test" - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/colors.css b/enyo/tools/minifier/node_modules/less/test/css/colors.css deleted file mode 100644 index 8ff5bad..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/colors.css +++ /dev/null @@ -1,77 +0,0 @@ -#yelow #short { - color: #fea; -} -#yelow #long { - color: #ffeeaa; -} -#yelow #rgba { - color: rgba(255, 238, 170, 0.1); -} -#yelow #argb { - color: #1affeeaa; -} -#blue #short { - color: #00f; -} -#blue #long { - color: #0000ff; -} -#blue #rgba { - color: rgba(0, 0, 255, 0.1); -} -#blue #argb { - color: #1a0000ff; -} -#alpha #hsla { - color: rgba(61, 45, 41, 0.6); -} -#overflow .a { - color: #000000; -} -#overflow .b { - color: #ffffff; -} -#overflow .c { - color: #ffffff; -} -#overflow .d { - color: #00ff00; -} -#grey { - color: #c8c8c8; -} -#808080 { - color: #808080; -} -#00ff00 { - color: #00ff00; -} -.lightenblue { - color: #3333ff; -} -.darkenblue { - color: #0000cc; -} -.unknowncolors { - color: blue2; - border: 2px solid superred; -} -.transparent { - color: transparent; - background-color: rgba(0, 0, 0, 0); -} -#alpha #fromvar { - opacity: 0.7; -} -#alpha #short { - opacity: 1; -} -#alpha #long { - opacity: 1; -} -#alpha #rgba { - opacity: 0.2; -} -#alpha #hsl { - opacity: 1; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/comments.css b/enyo/tools/minifier/node_modules/less/test/css/comments.css deleted file mode 100644 index 352dd48..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/comments.css +++ /dev/null @@ -1,56 +0,0 @@ -/******************\ -* * -* Comment Header * -* * -\******************/ -/* - - Comment - -*/ -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ -/* @group Variables -------------------- */ -#comments { - /**/ - color: red; - /* A C-style comment */ - - background-color: orange; - font-size: 12px; - /* lost comment */ - content: "content"; - border: 1px solid black; - padding: 0; - margin: 2em; -} -/* commented out - #more-comments { - color: grey; - } -*/ -.selector, -.lots, -.comments { - color: #808080, /* blue */ #ffa500; - -webkit-border-radius: 2px /* webkit only */; - -moz-border-radius: 8px /* moz only with operation */; -} -#last { - color: #0000ff; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css-3.css b/enyo/tools/minifier/node_modules/less/test/css/css-3.css deleted file mode 100644 index 1f4da32..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/css-3.css +++ /dev/null @@ -1,98 +0,0 @@ -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); - transform: rotateX(45deg); -} -.item[data-cra_zy-attr1b-ut3=bold] { - font-weight: bold; -} -p:not([class*="lead"]) { - color: black; -} -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} -div#id.class[a=1][b=2].class:not(1) { - color: white; -} -ul.comma > li:not(:only-child)::after { - color: white; -} -ol.comma > li:nth-last-child(2)::after { - color: white; -} -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} -a[href^="http://"] { - color: black; -} -a[href$="http://"] { - color: black; -} -form[data-disabled] { - color: black; -} -p::before { - color: black; -} -#issue322 { - -webkit-animation: anim2 7s infinite ease-in-out; -} -@-webkit-keyframes frames { - 0% { - border: 1px; - } - 5.5% { - border: 2px; - } - 100% { - border: 3px; - } -} -@keyframes fontbulger1 { - to { - font-size: 15px; - } - from, - to { - font-size: 12px; - } - 0%, - 100% { - font-size: 12px; - } -} -.units { - font: 1.2rem/2rem; - font: 8vw/9vw; - font: 10vh/12vh; - font: 12vm/15vm; - font: 12vmin/15vmin; - font: 1.2ch/1.5ch; -} -@supports ( box-shadow: 2px 2px 2px black ) or - ( -moz-box-shadow: 2px 2px 2px black ) { - .outline { - box-shadow: 2px 2px 2px black; - -moz-box-shadow: 2px 2px 2px black; - } -} -@-x-document url-prefix(""github.com"") { - h1 { - color: red; - } -} -@viewport { - font-size: 10px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css b/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css deleted file mode 100644 index 4d343aa..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/css-escapes.css +++ /dev/null @@ -1,24 +0,0 @@ -.escape\|random\|char { - color: red; -} -.mixin\!tUp { - font-weight: bold; -} -.\34 04 { - background: red; -} -.\34 04 strong { - color: #ff00ff; - font-weight: bold; -} -.trailingTest\+ { - color: red; -} -/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ -\62\6c\6f \63 \6B \0071 \000075o\74 e { - color: silver; -} -[ng\:cloak], -ng\:form { - display: none; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/css.css b/enyo/tools/minifier/node_modules/less/test/css/css.css deleted file mode 100644 index e0e0aa7..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/css.css +++ /dev/null @@ -1,100 +0,0 @@ -@charset "utf-8"; -div { - color: black; -} -div { - width: 99%; -} -* { - min-width: 45em; -} -h1, -h2 > a > p, -h3 { - color: none; -} -div.class { - color: blue; -} -div#id { - color: green; -} -.class#id { - color: purple; -} -.one.two.three { - color: grey; -} -@media print { - font-size: 3em; -} -@media screen { - font-size: 10px; -} -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} -a:hover, -a:link { - color: #999; -} -p, -p:first-child { - text-transform: none; -} -q:lang(no) { - quotes: none; -} -p + h1 { - font-size: 2.2em; -} -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - font: 100%/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; - font: 0/0 a; -} -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff)); - margin: ; - filter: alpha(opacity=100); -} -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} -#data-uri { - background: url(data:image/png;charset=utf-8;base64, - kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ - k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U - kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); - background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); - background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); -} -#svg-data-uri { - background: transparent url('data:image/svg+xml, '); -} -@font-face { - font-family: font-a; -} -@font-face { - font-family: font-b; -} -.æøå { - margin: 0; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css deleted file mode 100644 index dfe93c0..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-all.css +++ /dev/null @@ -1,39 +0,0 @@ -/* line 21, {pathimport}test.less */ -@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"21";}} -.tst3 { - color: grey; -} -/* line 13, {path}linenumbers.less */ -@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"13";}} -.test1 { - color: black; -} -/* line 4, {path}linenumbers.less */ -@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"4";}} -.test2 { - color: red; -} -@media all { - /* line 3, {pathimport}test.less */ - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"3";}} - .tst { - color: black; - } -} -@media all and screen { - /* line 5, {pathimport}test.less */ - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"5";}} - .tst { - color: red; - } - /* line 7, {pathimport}test.less */ - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"7";}} - .tst .tst3 { - color: white; - } -} -/* line 16, {pathimport}test.less */ -@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"16";}} -.tst2 { - color: white; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css deleted file mode 100644 index 09e2cc0..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-comments.css +++ /dev/null @@ -1,32 +0,0 @@ -/* line 21, {pathimport}test.less */ -.tst3 { - color: grey; -} -/* line 13, {path}linenumbers.less */ -.test1 { - color: black; -} -/* line 4, {path}linenumbers.less */ -.test2 { - color: red; -} -@media all { - /* line 3, {pathimport}test.less */ - .tst { - color: black; - } -} -@media all and screen { - /* line 5, {pathimport}test.less */ - .tst { - color: red; - } - /* line 7, {pathimport}test.less */ - .tst .tst3 { - color: white; - } -} -/* line 16, {pathimport}test.less */ -.tst2 { - color: white; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css b/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css deleted file mode 100644 index cbcbd17..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/debug/linenumbers-mediaquery.css +++ /dev/null @@ -1,32 +0,0 @@ -@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"21";}} -.tst3 { - color: grey; -} -@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"13";}} -.test1 { - color: black; -} -@media -sass-debug-info{filename{font-family:"{path}linenumbers.less";}line{font-family:"4";}} -.test2 { - color: red; -} -@media all { - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"3";}} - .tst { - color: black; - } -} -@media all and screen { - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"5";}} - .tst { - color: red; - } - @media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"7";}} - .tst .tst3 { - color: white; - } -} -@media -sass-debug-info{filename{font-family:"{pathimport}test.less";}line{font-family:"16";}} -.tst2 { - color: white; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/functions.css b/enyo/tools/minifier/node_modules/less/test/css/functions.css deleted file mode 100644 index a1413ef..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/functions.css +++ /dev/null @@ -1,92 +0,0 @@ -#functions { - color: #660000; - width: 16; - height: undefined("self"); - border-width: 5; - variable: 11; - background: linear-gradient(#000000, #ffffff); -} -#built-in { - escaped: -Some::weird(#thing, y); - lighten: #ffcccc; - darken: #330000; - saturate: #203c31; - desaturate: #29332f; - greyscale: #2e2e2e; - spin-p: #bf6a40; - spin-n: #bf4055; - luma-white: 100%; - luma-black: 0%; - luma-black-alpha: 0%; - luma-red: 21%; - luma-green: 72%; - luma-blue: 7%; - luma-yellow: 93%; - luma-cyan: 79%; - luma-white-alpha: 50%; - contrast-white: #000000; - contrast-black: #ffffff; - contrast-red: #ffffff; - contrast-green: #000000; - contrast-blue: #ffffff; - contrast-yellow: #000000; - contrast-cyan: #000000; - contrast-light: #111111; - contrast-dark: #eeeeee; - contrast-light-thresh: #111111; - contrast-dark-thresh: #eeeeee; - contrast-high-thresh: #eeeeee; - contrast-low-thresh: #111111; - format: "rgb(32, 128, 64)"; - format-string: "hello world"; - format-multiple: "hello earth 2"; - format-url-encode: "red is %23ff0000"; - eformat: rgb(32, 128, 64); - hue: 98; - saturation: 12%; - lightness: 95%; - red: 255; - green: 255; - blue: 255; - rounded: 11; - rounded-two: 10.67; - roundedpx: 3px; - roundedpx-three: 3.333px; - percentage: 20%; - color: #ff0011; - tint: #898989; - tint-full: #ffffff; - tint-percent: #898989; - shade: #686868; - shade-full: #000000; - shade-percent: #686868; - mix: #ff3300; - mix-0: #ffff00; - mix-100: #ff0000; - mix-weightless: #ff8000; -} -#built-in .is-a { - color: true; - color1: true; - color2: true; - keyword: true; - number: true; - string: true; - pixel: true; - percent: true; - em: true; -} -#alpha { - alpha: rgba(153, 94, 51, 0.6); -} -#blendmodes { - multiply: #ed0000; - screen: #f600f6; - overlay: #ed0000; - softlight: #ff0000; - hardlight: #0000ed; - difference: #f600f6; - exclusion: #f600f6; - average: #7b007b; - negation: #d73131; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css b/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css deleted file mode 100644 index 007aa53..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/ie-filters.css +++ /dev/null @@ -1,9 +0,0 @@ -.nav { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=20); - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0); -} -.evalTest1 { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30); - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=5); -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/import-once.css b/enyo/tools/minifier/node_modules/less/test/css/import-once.css deleted file mode 100644 index 98e2243..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/import-once.css +++ /dev/null @@ -1,6 +0,0 @@ -@import "import-test-d.css"; - -@import "../import-test-d.css"; -#import { - color: #ff0000; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/import.css b/enyo/tools/minifier/node_modules/less/test/css/import.css deleted file mode 100644 index 89dc162..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/import.css +++ /dev/null @@ -1,23 +0,0 @@ -@import "import-test-d.css"; - -@import url(http://fonts.googleapis.com/css?family=Open+Sans); - -@import url(something.css) screen and (color) and (max-width: 600px); -#import { - color: #ff0000; -} -.mixin { - height: 10px; - color: #ff0000; -} -#import-test { - height: 10px; - color: #ff0000; - width: 10px; - height: 30%; -} -@media screen and (max-width: 600px) { - body { - width: 100%; - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/javascript.css b/enyo/tools/minifier/node_modules/less/test/css/javascript.css deleted file mode 100644 index 8268ab3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/javascript.css +++ /dev/null @@ -1,23 +0,0 @@ -.eval { - js: 42; - js: 2; - js: "hello world"; - js: 1, 2, 3; - title: "string"; - ternary: true; - multiline: 2; -} -.scope { - var: 42; - escaped: 7px; -} -.vars { - width: 8; -} -.escape-interpol { - width: hello world; -} -.arrays { - ary: "1, 2, 3"; - ary1: "1, 2, 3"; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css b/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css deleted file mode 100644 index 1adfb8f..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/lazy-eval.css +++ /dev/null @@ -1,3 +0,0 @@ -.lazy-eval { - width: 100%; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/media.css b/enyo/tools/minifier/node_modules/less/test/css/media.css deleted file mode 100644 index 2be53ef..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/media.css +++ /dev/null @@ -1,176 +0,0 @@ -@media print { - .class { - color: blue; - } - .class .sub { - width: 42; - } - .top, - header > h1 { - color: #444444; - } -} -@media screen { - body { - max-width: 480; - } -} -@media all and (device-aspect-ratio: 16/9) { - body { - max-width: 800px; - } -} -@media all and (orientation: portrait) { - aside { - float: none; - } -} -@media handheld and (min-width: 42), screen and (min-width: 20em) { - body { - max-width: 480px; - } -} -@media print { - body { - padding: 20px; - } - body header { - background-color: red; - } -} -@media print and (orientation: landscape) { - body { - margin-left: 20px; - } -} -@media screen { - .sidebar { - width: 300px; - } -} -@media screen and (orientation: landscape) { - .sidebar { - width: 500px; - } -} -@media a { - -} -@media a and b { - .first .second .third { - width: 300px; - } - .first .second .fourth { - width: 3; - } -} -@media a and b and c { - .first .second .third { - width: 500px; - } -} -@media a, b and c { - body { - width: 95%; - } -} -@media a and x, b and c and x, a and y, b and c and y { - body { - width: 100%; - } -} -.a { - background: black; -} -@media handheld { - .a { - background: white; - } -} -@media handheld and (max-width: 100px) { - .a { - background: red; - } -} -.b { - background: black; -} -@media handheld { - .b { - background: white; - } -} -@media handheld and (max-width: 200px) { - .b { - background: red; - } -} -@media only screen and (max-width: 200px) { - width: 480px; -} -@media print { - @page :left { - margin: 0.5cm; - } - @page :right { - margin: 0.5cm; - } - @page Test:first { - margin: 1cm; - } - @page :first { - size: 8.5in 11in;@top-left { - margin: 1cm; - } - @top-left-corner { - margin: 1cm; - } - @top-center { - margin: 1cm; - } - @top-right { - margin: 1cm; - } - @top-right-corner { - margin: 1cm; - } - @bottom-left { - margin: 1cm; - } - @bottom-left-corner { - margin: 1cm; - } - @bottom-center { - margin: 1cm; - } - @bottom-right { - margin: 1cm; - } - @bottom-right-corner { - margin: 1cm; - } - @left-top { - margin: 1cm; - } - @left-middle { - margin: 1cm; - } - @left-bottom { - margin: 1cm; - } - @right-top { - margin: 1cm; - } - @right-middle { - content: "Page " counter(page); - } - @right-bottom { - margin: 1cm; - } - } -} -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { - .b { - background: red; - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css deleted file mode 100644 index d5b67f3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-args.css +++ /dev/null @@ -1,74 +0,0 @@ -#hidden { - color: transparent; -} -#hidden1 { - color: transparent; -} -.two-args { - color: blue; - width: 10px; - height: 99%; - border: 2px dotted #000000; -} -.one-arg { - width: 15px; - height: 49%; -} -.no-parens { - width: 5px; - height: 49%; -} -.no-args { - width: 5px; - height: 49%; -} -.var-args { - width: 45; - height: 17%; -} -.multi-mix { - width: 10px; - height: 29%; - margin: 4; - padding: 5; -} -body { - padding: 30px; - color: #ff0000; -} -.scope-mix { - width: 8; -} -.content { - width: 600px; -} -.content .column { - margin: 600px; -} -#same-var-name { - radius: 5px; -} -#var-inside { - width: 10px; -} -.arguments { - border: 1px solid #000000; - width: 1px; -} -.arguments2 { - border: 0px; - width: 0px; -} -.arguments3 { - border: 0px; - width: 0px; -} -.arguments4 { - border: 0 1 2 3 4; - rest: 1 2 3 4; - width: 0; -} -.edge-case { - border: "{"; - width: "{"; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css deleted file mode 100644 index b1021b6..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-closure.css +++ /dev/null @@ -1,9 +0,0 @@ -.class { - width: 99px; -} -.overwrite { - width: 99px; -} -.nested .class { - width: 5px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css deleted file mode 100644 index cd94c01..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-guards.css +++ /dev/null @@ -1,68 +0,0 @@ -.light1 { - color: white; - margin: 1px; -} -.light2 { - color: black; - margin: 1px; -} -.max1 { - width: 6; -} -.max2 { - width: 8; -} -.glob1 { - margin: auto auto; -} -.ops1 { - height: gt-or-eq; - height: lt-or-eq; -} -.ops2 { - height: gt-or-eq; - height: not-eq; -} -.ops3 { - height: lt-or-eq; - height: not-eq; -} -.default1 { - content: default; -} -.test1 { - content: "true."; -} -.test2 { - content: "false."; -} -.test3 { - content: "false."; -} -.test4 { - content: "false."; -} -.test5 { - content: "false."; -} -.bool1 { - content: true and true; - content: true; - content: false, true; - content: false and true and true, true; - content: false, true and true; - content: false, false, true; - content: false, true and true and true, false; - content: not false; - content: not false and false, not false; -} -.colorguardtest { - content: is #ff0000; - content: is not #0000ff its #ff0000; - content: is not #0000ff its #800080; -} -.stringguardtest { - content: is theme1; - content: is not theme2; - content: is theme1 no quotes; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css deleted file mode 100644 index 2f74c64..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-important.css +++ /dev/null @@ -1,17 +0,0 @@ -.class { - border: 1; - boxer: 1; - border: 2 !important; - boxer: 2 !important; - border: 3; - boxer: 3; - border: 4 !important; - boxer: 4 !important; - border: 5; - boxer: 5; - border: 0 !important; - boxer: 0 !important; - border: 9 !important; - border: 9; - boxer: 9; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css deleted file mode 100644 index 1c1afaf..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-named-args.css +++ /dev/null @@ -1,20 +0,0 @@ -.named-arg { - color: blue; - width: 5px; - height: 99%; - text-align: center; -} -.class { - width: 5px; - height: 19%; -} -.named-args2 { - width: 15px; - height: 49%; - color: #646464; -} -.named-args3 { - width: 5px; - height: 29%; - color: #123456; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css deleted file mode 100644 index 6378c47..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-nested.css +++ /dev/null @@ -1,14 +0,0 @@ -.class .inner { - height: 300; -} -.class .inner .innest { - width: 30; - border-width: 60; -} -.class2 .inner { - height: 600; -} -.class2 .inner .innest { - width: 60; - border-width: 120; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css b/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css deleted file mode 100644 index 8b82833..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins-pattern.css +++ /dev/null @@ -1,47 +0,0 @@ -.zero { - variadic: true; - zero: 0; - one: 1; - two: 2; - three: 3; -} -.one { - variadic: true; - one: 1; - one-req: 1; - two: 2; - three: 3; -} -.two { - variadic: true; - two: 2; - three: 3; -} -.three { - variadic: true; - three-req: 3; - three: 3; -} -.left { - left: 1; -} -.right { - right: 1; -} -.border-right { - color: black; - border-right: 4px; -} -.border-left { - color: black; - border-left: 4px; -} -.only-right { - right: 33; -} -.only-left { - left: 33; -} -.left-right { - both: 330; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/mixins.css b/enyo/tools/minifier/node_modules/less/test/css/mixins.css deleted file mode 100644 index c5d3b22..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/mixins.css +++ /dev/null @@ -1,108 +0,0 @@ -.mixin { - border: 1px solid black; -} -.mixout { - border-color: orange; -} -.borders { - border-style: dashed; -} -#namespace .borders { - border-style: dotted; -} -#namespace .biohazard { - content: "death"; -} -#namespace .biohazard .man { - color: transparent; -} -#theme > .mixin { - background-color: grey; -} -#container { - color: black; - border: 1px solid black; - border-color: orange; - background-color: grey; -} -#header .milk { - color: white; - border: 1px solid black; - background-color: grey; -} -#header #cookie { - border-style: dashed; -} -#header #cookie .chips { - border-style: dotted; -} -#header #cookie .chips .calories { - color: black; - border: 1px solid black; - border-color: orange; - background-color: grey; -} -.secure-zone { - color: transparent; -} -.direct { - border-style: dotted; -} -.bo, -.bar { - width: 100%; -} -.bo { - border: 1px; -} -.ar.bo.ca { - color: black; -} -.jo.ki { - background: none; -} -.extended { - width: 100%; - border: 1px; - background: none; -} -.foo .bar { - width: 100%; -} -.underParents { - color: red; -} -.parent .underParents { - color: red; -} -* + h1 { - margin-top: 25px; -} -legend + h1 { - margin-top: 0; -} -h1 + * { - margin-top: 10px; -} -* + h2 { - margin-top: 20px; -} -legend + h2 { - margin-top: 0; -} -h2 + * { - margin-top: 8px; -} -* + h3 { - margin-top: 15px; -} -legend + h3 { - margin-top: 0; -} -h3 + * { - margin-top: 5px; -} -.error { - background-image: "/a.png"; - background-position: center center; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/operations.css b/enyo/tools/minifier/node_modules/less/test/css/operations.css deleted file mode 100644 index fb9e0af..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/operations.css +++ /dev/null @@ -1,49 +0,0 @@ -#operations { - color: #111111; - height: 9px; - width: 3em; - substraction: 0; - division: 1; -} -#operations .spacing { - height: 9px; - width: 3em; -} -.with-variables { - height: 16em; - width: 24em; - size: 1cm; -} -.with-functions { - color: #646464; - color: #ff8080; - color: #c94a4a; -} -.negative { - height: 0px; - width: 4px; -} -.shorthands { - padding: -1px 2px 0 -4px; -} -.rem-dimensions { - font-size: 5.5rem; -} -.colors { - color: #123; - border-color: #334455; - background-color: #000000; -} -.colors .other { - color: #222222; - border-color: #222222; -} -.negations { - variable: -4px; - variable1: 0px; - variable2: 0px; - variable3: 8px; - variable4: 0px; - paren: -4px; - paren2: 16px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/parens.css b/enyo/tools/minifier/node_modules/less/test/css/parens.css deleted file mode 100644 index 36487fe..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/parens.css +++ /dev/null @@ -1,20 +0,0 @@ -.parens { - border: 2px solid #000000; - margin: 1px 3px 16 3; - width: 36; - padding: 2px 36px; -} -.more-parens { - padding: 8 4 4 4px; - width: 96; - height: 113; - margin: 12; -} -.nested-parens { - width: 71; - height: 6; -} -.mixed-units { - margin: 2px 4em 1 5pc; - padding: 6px 1em 2px 2; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/rulesets.css b/enyo/tools/minifier/node_modules/less/test/css/rulesets.css deleted file mode 100644 index 408c76a..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/rulesets.css +++ /dev/null @@ -1,33 +0,0 @@ -#first > .one { - font-size: 2em; -} -#first > .one > #second .two > #deux { - width: 50%; -} -#first > .one > #second .two > #deux #third { - height: 100%; -} -#first > .one > #second .two > #deux #third:focus { - color: black; -} -#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth { - color: purple; -} -#first > .one > #second .two > #deux #fourth, -#first > .one > #second .two > #deux #five, -#first > .one > #second .two > #deux #six { - color: #110000; -} -#first > .one > #second .two > #deux #fourth .seven, -#first > .one > #second .two > #deux #five .seven, -#first > .one > #second .two > #deux #six .seven, -#first > .one > #second .two > #deux #fourth .eight > #nine, -#first > .one > #second .two > #deux #five .eight > #nine, -#first > .one > #second .two > #deux #six .eight > #nine { - border: 1px solid black; -} -#first > .one > #second .two > #deux #fourth #ten, -#first > .one > #second .two > #deux #five #ten, -#first > .one > #second .two > #deux #six #ten { - color: red; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/scope.css b/enyo/tools/minifier/node_modules/less/test/css/scope.css deleted file mode 100644 index 11feda8..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/scope.css +++ /dev/null @@ -1,15 +0,0 @@ -.tiny-scope { - color: #998899; -} -.scope1 { - color: #0000ff; - border-color: #000000; -} -.scope1 .scope2 { - color: #0000ff; -} -.scope1 .scope2 .scope3 { - color: #ff0000; - border-color: #000000; - background-color: #ffffff; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/selectors.css b/enyo/tools/minifier/node_modules/less/test/css/selectors.css deleted file mode 100644 index ee8fe60..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/selectors.css +++ /dev/null @@ -1,130 +0,0 @@ -h1 a:hover, -h2 a:hover, -h3 a:hover, -h1 p:hover, -h2 p:hover, -h3 p:hover { - color: red; -} -#all { - color: blue; -} -#the { - color: blue; -} -#same { - color: blue; -} -ul, -li, -div, -q, -blockquote, -textarea { - margin: 0; -} -td { - margin: 0; - padding: 0; -} -td, -input { - line-height: 1em; -} -a { - color: red; -} -a:hover { - color: blue; -} -div a { - color: green; -} -p a span { - color: yellow; -} -.foo .bar .qux, -.foo .baz .qux { - display: block; -} -.qux .foo .bar, -.qux .foo .baz { - display: inline; -} -.qux.foo .bar, -.qux.foo .baz { - display: inline-block; -} -.qux .foo .bar .biz, -.qux .foo .baz .biz { - display: none; -} -.a.b.c { - color: red; -} -.c .b.a { - color: red; -} -.foo .p.bar { - color: red; -} -.foo.p.bar { - color: red; -} -.foo + .foo { - background: amber; -} -.foo + .foo { - background: amber; -} -.foo + .foo, -.foo + .bar, -.bar + .foo, -.bar + .bar { - background: amber; -} -.foo a > .foo a, -.foo a > .bar a, -.foo a > .foo b, -.foo a > .bar b, -.bar a > .foo a, -.bar a > .bar a, -.bar a > .foo b, -.bar a > .bar b, -.foo b > .foo a, -.foo b > .bar a, -.foo b > .foo b, -.foo b > .bar b, -.bar b > .foo a, -.bar b > .bar a, -.bar b > .foo b, -.bar b > .bar b { - background: amber; -} -.other ::fnord { - color: #ff0000; -} -.other::fnord { - color: #ff0000; -} -.other ::bnord { - color: #ff0000; -} -.other::bnord { - color: #ff0000; -} -.blood { - color: red; -} -.blood { - color: red; -} -.bloodred { - color: green; -} -#blood.blood.red.black { - color: black; -} -:nth-child(3):nth-child(3) { - second-use: deprecated; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/strings.css b/enyo/tools/minifier/node_modules/less/test/css/strings.css deleted file mode 100644 index 0c34134..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/strings.css +++ /dev/null @@ -1,40 +0,0 @@ -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; - escapes: "\"hello\" \\world"; - escapes2: "\"llo"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; - semi-colon: ';'; -} -#escaped { - filter: DX.Transform.MS.BS.filter(opacity=50); -} -#one-line { - image: url(http://tooks.com); -} -#crazy { - image: url(http://), "}", url("http://}"); -} -#interpolation { - url: "http://lesscss.org/dev/image.jpg"; - url2: "http://lesscss.org/image-256.jpg"; - url3: "http://lesscss.org#445566"; - url4: "http://lesscss.org/hello"; - url5: "http://lesscss.org/54.4"; -} -.mix-mul-class { - color: #0000ff; - color: #ff0000; - color: #000000; - color: #ffa500; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/variables.css b/enyo/tools/minifier/node_modules/less/test/css/variables.css deleted file mode 100644 index 961fe69..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/variables.css +++ /dev/null @@ -1,27 +0,0 @@ -.variables { - width: 14cm; -} -.variables { - height: 24px; - color: #888888; - font-family: "Trebuchet MS", Verdana, sans-serif; - quotes: "~" "~"; -} -.redefinition { - three: 3; -} -.values { - font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; - color: #888888 !important; - url: url('Trebuchet'); - multi: something 'A', B, C, 'Trebuchet'; -} -.variable-names { - name: 'hello'; -} -.alpha { - filter: alpha(opacity=42); -} -a:nth-child(2) { - border: 1px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/css/whitespace.css b/enyo/tools/minifier/node_modules/less/test/css/whitespace.css deleted file mode 100644 index 74c9b65..0000000 --- a/enyo/tools/minifier/node_modules/less/test/css/whitespace.css +++ /dev/null @@ -1,42 +0,0 @@ -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white ; -} -.white, -.space, -.mania { - color: white; -} -.no-semi-column { - color: #ffffff; -} -.no-semi-column { - color: white; - white-space: pre; -} -.no-semi-column { - border: 2px solid #ffffff; -} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.sel .newline_ws .tab_ws { - color: white; - background-position: 45 -23; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less-test.js b/enyo/tools/minifier/node_modules/less/test/less-test.js deleted file mode 100644 index 5504168..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less-test.js +++ /dev/null @@ -1,174 +0,0 @@ -var path = require('path'), - fs = require('fs'), - sys = require('util'); - -var less = require('../lib/less'); -var stylize = require('../lib/less/lessc_helper').stylize; - -var oneTestOnly = process.argv[2]; - -var totalTests = 0, - failedTests = 0, - passedTests = 0; - -less.tree.functions.add = function (a, b) { - return new(less.tree.Dimension)(a.value + b.value); -}; -less.tree.functions.increment = function (a) { - return new(less.tree.Dimension)(a.value + 1); -}; -less.tree.functions._color = function (str) { - if (str.value === "evil red") { return new(less.tree.Color)("600") } -}; - -sys.puts("\n" + stylize("LESS", 'underline') + "\n"); - -runTestSet(); - -runTestSet(null, "errors/", function(name, err, compiledLess, doReplacements) { - fs.readFile(path.join('test/less/', name) + '.txt', 'utf-8', function (e, expectedErr) { - sys.print("- " + name + ": "); - expectedErr = doReplacements(expectedErr, 'test/less/errors/'); - if (!err) { - if (compiledLess) { - fail("No Error", 'red'); - } else { - fail("No Error, No Output"); - } - } else { - var errMessage = less.formatError(err); - if (errMessage === expectedErr) { - ok('OK'); - } else { - difference("FAIL", expectedErr, errMessage); - } - } - sys.puts(""); - });}, null, function(input, directory) { - return input.replace( - "{path}", path.join(process.cwd(), "/test/less/errors/")) - .replace("{pathrel}", path.join("test", "less", "errors/")) - .replace(/\r\n/g, '\n'); - }); - -runTestSet({dumpLineNumbers: 'comments'}, "debug/", null, - function(name) { return name + '-comments'; }); -runTestSet({dumpLineNumbers: 'mediaquery'}, "debug/", null, - function(name) { return name + '-mediaquery'; }); -runTestSet({dumpLineNumbers: 'all'}, "debug/", null, - function(name) { return name + '-all'; }); - -function globalReplacements(input, directory) { - return input.replace(/\{path\}/g, path.join(process.cwd(), directory)) - .replace(/\{pathimport\}/g, path.join(process.cwd(), directory + "import/")) - .replace(/\r\n/g, '\n'); -} - -function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements) { - foldername = foldername || ""; - - if(!doReplacements) - doReplacements = globalReplacements; - - fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) { - if (! /\.less/.test(file)) { return } - - var name = foldername + path.basename(file, '.less'); - - if (oneTestOnly && name !== oneTestOnly) { return; } - - totalTests++; - - toCSS(options, path.join('test/less/', foldername + file), function (err, less) { - - if (verifyFunction) { - return verifyFunction(name, err, less, doReplacements); - } - var css_name = name; - if(nameModifier) css_name=nameModifier(name); - fs.readFile(path.join('test/css', css_name) + '.css', 'utf-8', function (e, css) { - sys.print("- " + css_name + ": ") - - css = css && doReplacements(css, 'test/less/' + foldername); - if (less === css) { ok('OK'); } - else if (err) { - fail("ERROR: " + (err && err.message)); - } else { - difference("FAIL", css, less); - } - sys.puts(""); - }); - }); - }); -} - -function diff(left, right) { - sys.puts(""); - require('diff').diffLines(left, right).forEach(function(item) { - if(item.added || item.removed) { - sys.print(stylize(item.value, item.added ? 'green' : 'red')); - } else { - sys.print(item.value); - } - }); -} - -function fail(msg) { - sys.print(stylize(msg, 'red')); - failedTests++; - endTest(); -} - -function difference(msg, left, right) { - sys.print(stylize(msg, 'yellow')); - failedTests++; - - diff(left, right); - endTest(); -} - -function ok(msg) { - sys.print(stylize(msg, 'green')); - passedTests++; - endTest(); -} - -function endTest() { - if (failedTests + passedTests === totalTests) { - sys.puts(""); - sys.puts(""); - if (failedTests > 0) { - sys.print(failedTests); - sys.print(stylize(" Failed", "red")); - sys.print(", " + passedTests + " passed"); - } else { - sys.print(stylize("All Passed ", "green")); - sys.print(passedTests + " run"); - } - } -} - -function toCSS(options, path, callback) { - var tree, css; - options = options || {}; - fs.readFile(path, 'utf-8', function (e, str) { - if (e) { return callback(e) } - - options.paths = [require('path').dirname(path)]; - options.filename = require('path').resolve(process.cwd(), path); - options.optimization = options.optimization || 0; - - new(less.Parser)(options).parse(str, function (err, tree) { - if (err) { - callback(err); - } else { - try { - css = tree.toCSS(); - callback(null, css); - } catch (e) { - callback(e); - } - } - }); - }); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/colors.less b/enyo/tools/minifier/node_modules/less/test/less/colors.less deleted file mode 100644 index d8038de..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/colors.less +++ /dev/null @@ -1,88 +0,0 @@ -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } - #argb { - color: argb(rgba(255, 238, 170, 0.1)); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } - #argb { - color: argb(rgba(0, 0, 255, 0.1)); - } -} - -#alpha #hsla { - color: hsla(11, 20%, 20%, 0.6); -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} - -.lightenblue { - color: lighten(blue, 10%); -} - -.darkenblue { - color: darken(blue, 10%); -} - -.unknowncolors { - color: blue2; - border: 2px solid superred; -} - -.transparent { - color: transparent; - background-color: rgba(0, 0, 0, 0); -} -#alpha { - @colorvar: rgba(150, 200, 150, 0.7); - #fromvar { - opacity: alpha(@colorvar); - } - #short { - opacity: alpha(#aaa); - } - #long { - opacity: alpha(#bababa); - } - #rgba { - opacity: alpha(rgba(50, 120, 95, 0.2)); - } - #hsl { - opacity: alpha(hsl(120, 100%, 50%)); - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/comments.less b/enyo/tools/minifier/node_modules/less/test/less/comments.less deleted file mode 100644 index 1b5c63e..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/comments.less +++ /dev/null @@ -1,65 +0,0 @@ -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; // }{ '" - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -.selector /* .with */, .lots, /* of */ .comments { - color: grey, /* blue */ orange; - -webkit-border-radius: 2px /* webkit only */; - -moz-border-radius: 2px * 4 /* moz only with operation */; -} - -#last { color: blue } -// diff --git a/enyo/tools/minifier/node_modules/less/test/less/css-3.less b/enyo/tools/minifier/node_modules/less/test/less/css-3.less deleted file mode 100644 index 0d72d18..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/css-3.less +++ /dev/null @@ -1,108 +0,0 @@ -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); - transform: rotateX(45deg); -} -.item[data-cra_zy-attr1b-ut3=bold] { - font-weight: bold; -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} - -#issue322 { - -webkit-animation: anim2 7s infinite ease-in-out; -} - -@-webkit-keyframes frames { - 0% { border: 1px } - 5.5% { border: 2px } - 100% { border: 3px } -} - -@keyframes fontbulger1 { - to { - font-size: 15px; - } - from,to { - font-size: 12px; - } - 0%,100% { - font-size: 12px; - } -} - -.units { - font: 1.2rem/2rem; - font: 8vw/9vw; - font: 10vh/12vh; - font: 12vm/15vm; - font: 12vmin/15vmin; - font: 1.2ch/1.5ch; -} - -@supports ( box-shadow: 2px 2px 2px black ) or - ( -moz-box-shadow: 2px 2px 2px black ) { - .outline { - box-shadow: 2px 2px 2px black; - -moz-box-shadow: 2px 2px 2px black; - } -} - -@-x-document url-prefix(""github.com"") { - h1 { - color: red; - } -} - -@viewport { - font-size: 10px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less b/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less deleted file mode 100644 index 6a4b283..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/css-escapes.less +++ /dev/null @@ -1,33 +0,0 @@ -@ugly: fuchsia; - -.escape\|random\|char { - color: red; -} - -.mixin\!tUp { - font-weight: bold; -} - -// class="404" -.\34 04 { - background: red; - - strong { - color: @ugly; - .mixin\!tUp; - } -} - -.trailingTest\+ { - color: red; -} - -/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ -\62\6c\6f \63 \6B \0071 \000075o\74 e { - color: silver; -} - -[ng\:cloak], -ng\:form { - display: none; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/css.less b/enyo/tools/minifier/node_modules/less/test/less/css.less deleted file mode 100644 index 2340f6e..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/css.less +++ /dev/null @@ -1,115 +0,0 @@ -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - font: 100%/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; - font: 0/0 a; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; - filter: alpha(opacity=100); -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#data-uri { - background: url(data:image/png;charset=utf-8;base64, - kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ - k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U - kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); - background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); - background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); -} - -#svg-data-uri { - background: transparent url('data:image/svg+xml, '); -} - -.def-font(@name) { - @font-face { - font-family: @name - } -} - -.def-font(font-a); -.def-font(font-b); - -.æøå { - margin: 0; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less b/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less deleted file mode 100644 index fe4f4f2..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/debug/import/test.less +++ /dev/null @@ -1,23 +0,0 @@ -.mixin_import1() { - @media all { - .tst { - color: black; - @media screen { - color: red; - .tst3 { - color: white; - } - } - } - } -} - -.mixin_import2() { - .tst2 { - color: white; - } -} - -.tst3 { - color: grey; -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less b/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less deleted file mode 100644 index dbf9770..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/debug/linenumbers.less +++ /dev/null @@ -1,21 +0,0 @@ -@import "import/test.less"; - -.start() { - .test2 { - color: red; - } -} - -.mix() { - color: black; -} - -.test1 { - .mix(); -} - -.start(); - -.mixin_import1(); - -.mixin_import2(); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less deleted file mode 100644 index a7d2639..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.less +++ /dev/null @@ -1 +0,0 @@ -#gaga /* Comment */ span { color: red } \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt deleted file mode 100644 index 571462f..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/comment-in-selector.txt +++ /dev/null @@ -1,2 +0,0 @@ -ParseError: Syntax Error on line 1 in {path}comment-in-selector.less:1:20 -1 #gaga /* Comment */ span { color: red } diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less deleted file mode 100644 index b740c11..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.less +++ /dev/null @@ -1 +0,0 @@ -@import "file-does-not-exist.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt deleted file mode 100644 index 2502e09..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-missing.txt +++ /dev/null @@ -1,3 +0,0 @@ -FileError: 'file-does-not-exist.less' wasn't found. - in {path}import-missing.less:1:0 -1 @import "file-does-not-exist.less"; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less deleted file mode 100644 index bf2c7f6..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.less +++ /dev/null @@ -1 +0,0 @@ -@import "this-statement-is-invalid.less" \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt deleted file mode 100644 index 60ae3f3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-no-semi.txt +++ /dev/null @@ -1,2 +0,0 @@ -ParseError: Syntax Error on line 1 in {path}import-no-semi.less:1:0 -1 @import "this-statement-is-invalid.less" diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less deleted file mode 100644 index 4280673..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.less +++ /dev/null @@ -1 +0,0 @@ -@import "imports/import-subfolder1.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt deleted file mode 100644 index 7bfd3b3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder1.txt +++ /dev/null @@ -1,3 +0,0 @@ -NameError: .mixin-not-defined is undefined in {pathrel}mixin-not-defined.less:11:0 -10 -11 .mixin-not-defined(); diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less deleted file mode 100644 index a6b9b9c..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.less +++ /dev/null @@ -1 +0,0 @@ -@import "imports/import-subfolder2.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt deleted file mode 100644 index 1c59d17..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/import-subfolder2.txt +++ /dev/null @@ -1,2 +0,0 @@ -ParseError: Syntax Error on line 1 in {pathrel}parse-error-curly-bracket.less:1:0 -1 }} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less deleted file mode 100644 index 24ec053..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder1.less +++ /dev/null @@ -1 +0,0 @@ -@import "subfolder/mixin-not-defined.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less deleted file mode 100644 index 6058ad1..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/import-subfolder2.less +++ /dev/null @@ -1 +0,0 @@ -@import "subfolder/parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less deleted file mode 100644 index 2bb2d09..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less +++ /dev/null @@ -1 +0,0 @@ -@import "../../mixin-not-defined.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less deleted file mode 100644 index f37fa9d..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less +++ /dev/null @@ -1 +0,0 @@ -@import "../../parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less deleted file mode 100644 index 9cffb9f..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.less +++ /dev/null @@ -1,3 +0,0 @@ -.scope { - var: `this.foo.toJS()`; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt deleted file mode 100644 index 16dc9b7..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/javascript-error.txt +++ /dev/null @@ -1,4 +0,0 @@ -SyntaxError: JavaScript evaluation error: 'TypeError: Cannot call method 'toJS' of undefined' in {path}javascript-error.less:2:26 -1 .scope { -2 var: `this.foo.toJS()`; -3 } diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less deleted file mode 100644 index e2dad5c..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.less +++ /dev/null @@ -1,11 +0,0 @@ - -.error-is-further-on() { -} - -.pad-here-to-reproduce-error-in() { -} - -.the-import-subfolder-test() { -} - -.mixin-not-defined(); \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt deleted file mode 100644 index f45de6a..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/mixin-not-defined.txt +++ /dev/null @@ -1,3 +0,0 @@ -NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less:11:0 -10 -11 .mixin-not-defined(); diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less deleted file mode 100644 index a2950a1..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.less +++ /dev/null @@ -1 +0,0 @@ -}} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt deleted file mode 100644 index f472c17..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-curly-bracket.txt +++ /dev/null @@ -1,2 +0,0 @@ -ParseError: Syntax Error on line 1 in {path}parse-error-curly-bracket.less:1:0 -1 }} diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less deleted file mode 100644 index 144a6ed..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.less +++ /dev/null @@ -1,2 +0,0 @@ -body { - background-color: #fff; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt deleted file mode 100644 index ea47da3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/parse-error-missing-bracket.txt +++ /dev/null @@ -1,2 +0,0 @@ -ParseError: missing closing `}` in {path}parse-error-missing-bracket.less:3:1 -2 background-color: #fff; diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less deleted file mode 100644 index 51bf6e3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.less +++ /dev/null @@ -1,3 +0,0 @@ -.test { - display/*/: block; /*sorry for IE5*/ -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt b/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt deleted file mode 100644 index c809140..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/errors/property-ie5-hack.txt +++ /dev/null @@ -1,4 +0,0 @@ -ParseError: Syntax Error on line 2 in {path}property-ie5-hack.less:2:2 -1 .test { -2 display/*/: block; /*sorry for IE5*/ -3 } diff --git a/enyo/tools/minifier/node_modules/less/test/less/functions.less b/enyo/tools/minifier/node_modules/less/test/less/functions.less deleted file mode 100644 index 6afed38..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/functions.less +++ /dev/null @@ -1,101 +0,0 @@ -#functions { - @var: 10; - @colors: #000, #fff; - color: _color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); - background: linear-gradient(@colors); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 40%); - darken: darken(#ff0000, 40%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - spin-p: spin(hsl(340, 50%, 50%), 40); - spin-n: spin(hsl(30, 50%, 50%), -40); - luma-white: luma(#fff); - luma-black: luma(#000); - luma-black-alpha: luma(rgba(0,0,0,0.5)); - luma-red: luma(#ff0000); - luma-green: luma(#00ff00); - luma-blue: luma(#0000ff); - luma-yellow: luma(#ffff00); - luma-cyan: luma(#00ffff); - luma-white-alpha: luma(rgba(255,255,255,0.5)); - contrast-white: contrast(#fff); - contrast-black: contrast(#000); - contrast-red: contrast(#ff0000); - contrast-green: contrast(#00ff00); - contrast-blue: contrast(#0000ff); - contrast-yellow: contrast(#ffff00); - contrast-cyan: contrast(#00ffff); - contrast-light: contrast(#fff, #111111, #eeeeee); - contrast-dark: contrast(#000, #111111, #eeeeee); - contrast-light-thresh: contrast(#fff, #111111, #eeeeee, 0.5); - contrast-dark-thresh: contrast(#000, #111111, #eeeeee, 0.5); - contrast-high-thresh: contrast(#555, #111111, #eeeeee, 0.6); - contrast-low-thresh: contrast(#555, #111111, #eeeeee, 0.1); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - format-multiple: %("hello %s %d", "earth", 2); - format-url-encode: %('red is %A', #ff0000); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); - - hue: hue(hsl(98, 12%, 95%)); - saturation: saturation(hsl(98, 12%, 95%)); - lightness: lightness(hsl(98, 12%, 95%)); - red: red(#f00); - green: green(#0f0); - blue: blue(#00f); - rounded: round(@r/3); - rounded-two: round(@r/3, 2); - roundedpx: round(10px / 3); - roundedpx-three: round(10px / 3, 3); - percentage: percentage(10px / 50); - color: color("#ff0011"); - tint: tint(#777777, 13); - tint-full: tint(#777777, 100); - tint-percent: tint(#777777, 13%); - shade: shade(#777777, 13); - shade-full: shade(#777777, 100); - shade-percent: shade(#777777, 13%); - - mix: mix(#ff0000, #ffff00, 80); - mix-0: mix(#ff0000, #ffff00, 0); - mix-100: mix(#ff0000, #ffff00, 100); - mix-weightless: mix(#ff0000, #ffff00); - - .is-a { - color: iscolor(#ddd); - color1: iscolor(red); - color2: iscolor(rgb(0, 0, 0)); - keyword: iskeyword(hello); - number: isnumber(32); - string: isstring("hello"); - pixel: ispixel(32px); - percent: ispercentage(32%); - em: isem(32em); - } -} - -#alpha { - alpha: darken(hsla(25, 50%, 50%, 0.6), 10%); -} - -#blendmodes { - multiply: multiply(#f60000, #f60000); - screen: screen(#f60000, #0000f6); - overlay: overlay(#f60000, #0000f6); - softlight: softlight(#f60000, #ffffff); - hardlight: hardlight(#f60000, #0000f6); - difference: difference(#f60000, #0000f6); - exclusion: exclusion(#f60000, #0000f6); - average: average(#f60000, #0000f6); - negation: negation(#f60000, #313131); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less b/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less deleted file mode 100644 index 3350b65..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/ie-filters.less +++ /dev/null @@ -1,15 +0,0 @@ -@fat: 0; -@cloudhead: "#000000"; - -.nav { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20); - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat); -} -.evalTest(@arg) { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg); -} -.evalTest1 { - .evalTest(30); - .evalTest(5); -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import-once.less b/enyo/tools/minifier/node_modules/less/test/less/import-once.less deleted file mode 100644 index f2f6362..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import-once.less +++ /dev/null @@ -1,3 +0,0 @@ -@import-once "import/import-once-test-c"; -@import-once "import/import-once-test-c"; -@import-once "import/deeper/import-once-test-a"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import.less b/enyo/tools/minifier/node_modules/less/test/less/import.less deleted file mode 100644 index 13ed5c5..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import.less +++ /dev/null @@ -1,11 +0,0 @@ -@import url("import/import-test-a.less"); -@import url(http://fonts.googleapis.com/css?family=Open+Sans); - -@import url(something.css) screen and (color) and (max-width: 600px); - -#import-test { - .mixin; - width: 10px; - height: @a + 10%; -} -@import "import/import-test-e" screen and (max-width: 600px); diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less b/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less deleted file mode 100644 index 2c399fa..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/deeper/import-once-test-a.less +++ /dev/null @@ -1 +0,0 @@ -@import-once "../import-test-d.css"; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less deleted file mode 100644 index 838fabc..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-once-test-c.less +++ /dev/null @@ -1,7 +0,0 @@ - -@import-once "import-test-d.css"; -@c: red; - -#import { - color: @c; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less deleted file mode 100644 index 7409d07..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-a.less +++ /dev/null @@ -1,2 +0,0 @@ -@import "import-test-b.less"; -@a: 20%; diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less deleted file mode 100644 index ce2d35a..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-b.less +++ /dev/null @@ -1,8 +0,0 @@ -@import "import-test-c"; - -@b: 100%; - -.mixin { - height: 10px; - color: @c; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less deleted file mode 100644 index 111266b..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-c.less +++ /dev/null @@ -1,7 +0,0 @@ - -@import "import-test-d.css"; -@c: red; - -#import { - color: @c; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css deleted file mode 100644 index 30575f0..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-d.css +++ /dev/null @@ -1 +0,0 @@ -#css { color: yellow; } diff --git a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less b/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less deleted file mode 100644 index 98b84b0..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/import/import-test-e.less +++ /dev/null @@ -1,2 +0,0 @@ - -body { width: 100% } diff --git a/enyo/tools/minifier/node_modules/less/test/less/javascript.less b/enyo/tools/minifier/node_modules/less/test/less/javascript.less deleted file mode 100644 index b76859e..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/javascript.less +++ /dev/null @@ -1,29 +0,0 @@ -.eval { - js: `42`; - js: `1 + 1`; - js: `"hello world"`; - js: `[1, 2, 3]`; - title: `typeof process.title`; - ternary: `(1 + 1 == 2 ? true : false)`; - multiline: `(function(){var x = 1 + 1; - return x})()`; -} -.scope { - @foo: 42; - var: `this.foo.toJS()`; - escaped: ~`2 + 5 + 'px'`; -} -.vars { - @var: `4 + 4`; - width: @var; -} -.escape-interpol { - @world: "world"; - width: ~`"hello" + " " + @{world}`; -} -.arrays { - @ary: 1, 2, 3; - @ary2: 1 2 3; - ary: `@{ary}.join(', ')`; - ary1: `@{ary2}.join(', ')`; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less b/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less deleted file mode 100644 index 72b3fd4..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/lazy-eval.less +++ /dev/null @@ -1,6 +0,0 @@ -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/media.less b/enyo/tools/minifier/node_modules/less/test/less/media.less deleted file mode 100644 index 3dc1aab..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/media.less +++ /dev/null @@ -1,179 +0,0 @@ - -// For now, variables can't be declared inside @media blocks. - -@var: 42; - -@media print { - .class { - color: blue; - .sub { - width: @var; - } - } - .top, header > h1 { - color: #222 * 2; - } -} - -@media screen { - @base: 8; - body { max-width: @base * 60; } -} - -@media all and (device-aspect-ratio: 16/9) { - body { max-width: 800px; } -} - -@media all and (orientation:portrait) { - aside { float: none; } -} - -@media handheld and (min-width: @var), screen and (min-width: 20em) { - body { - max-width: 480px; - } -} - -body { - @media print { - padding: 20px; - - header { - background-color: red; - } - - @media (orientation:landscape) { - margin-left: 20px; - } - } -} - -@media screen { - .sidebar { - width: 300px; - @media (orientation: landscape) { - width: 500px; - } - } -} - -@media a { - .first { - @media b { - .second { - .third { - width: 300px; - @media c { - width: 500px; - } - } - .fourth { - width: 3; - } - } - } - } -} - -body { - @media a, b and c { - width: 95%; - - @media x, y { - width: 100%; - } - } -} - -.mediaMixin(@fallback: 200px) { - background: black; - - @media handheld { - background: white; - - @media (max-width: @fallback) { - background: red; - } - } -} - -.a { - .mediaMixin(100px); -} - -.b { - .mediaMixin(); -} -@smartphone: ~"only screen and (max-width: 200px)"; -@media @smartphone { - width: 480px; -} - -@media print { - @page :left { - margin: 0.5cm; - } - @page :right { - margin: 0.5cm; - } - @page Test:first { - margin: 1cm; - } - @page :first { - size: 8.5in 11in; - @top-left { - margin: 1cm; - } - @top-left-corner { - margin: 1cm; - } - @top-center { - margin: 1cm; - } - @top-right { - margin: 1cm; - } - @top-right-corner { - margin: 1cm; - } - @bottom-left { - margin: 1cm; - } - @bottom-left-corner { - margin: 1cm; - } - @bottom-center { - margin: 1cm; - } - @bottom-right { - margin: 1cm; - } - @bottom-right-corner { - margin: 1cm; - } - @left-top { - margin: 1cm; - } - @left-middle { - margin: 1cm; - } - @left-bottom { - margin: 1cm; - } - @right-top { - margin: 1cm; - } - @right-middle { - content: "Page " counter(page); - } - @right-bottom { - margin: 1cm; - } - } -} - -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { - .b { - background: red; - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less deleted file mode 100644 index ea43a0a..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-args.less +++ /dev/null @@ -1,130 +0,0 @@ -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; // asd -} - -#hidden { - .hidden; -} - -#hidden1 { - .hidden(); -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } - -.mixin-arguments (@width: 0px, ...) { - border: @arguments; - width: @width; -} - -.arguments { - .mixin-arguments(1px, solid, black); -} -.arguments2 { - .mixin-arguments(); -} -.arguments3 { - .mixin-arguments; -} - -.mixin-arguments2 (@width, @rest...) { - border: @arguments; - rest: @rest; - width: @width; -} -.arguments4 { - .mixin-arguments2(0, 1, 2, 3, 4); -} - -// Edge cases - -.edge-case { - .mixin-arguments("{"); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less deleted file mode 100644 index 01251d2..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-closure.less +++ /dev/null @@ -1,26 +0,0 @@ -.scope { - @var: 99px; - .mixin () { - width: @var; - } -} - -.class { - .scope > .mixin; -} - -.overwrite { - @var: 0px; - .scope > .mixin; -} - -.nested { - @var: 5px; - .mixin () { - width: @var; - } - .class { - @var: 10px; - .mixin; - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less deleted file mode 100644 index 3e27c26..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-guards.less +++ /dev/null @@ -1,113 +0,0 @@ - -// Stacking, functions.. - -.light (@a) when (lightness(@a) > 50%) { - color: white; -} -.light (@a) when (lightness(@a) < 50%) { - color: black; -} -.light (@a) { - margin: 1px; -} - -.light1 { .light(#ddd) } -.light2 { .light(#444) } - -// Arguments against each other - -.max (@a, @b) when (@a > @b) { - width: @a; -} -.max (@a, @b) when (@a < @b) { - width: @b; -} - -.max1 { .max(3, 6) } -.max2 { .max(8, 1) } - -// Globals inside guards - -@g: auto; - -.glob (@a) when (@a = @g) { - margin: @a @g; -} -.glob1 { .glob(auto) } - -// Other operators - -.ops (@a) when (@a >= 0) { - height: gt-or-eq; -} -.ops (@a) when (@a =< 0) { - height: lt-or-eq; -} -.ops (@a) when not(@a = 0) { - height: not-eq; -} -.ops1 { .ops(0) } -.ops2 { .ops(1) } -.ops3 { .ops(-1) } - -// Scope and default values - -@a: auto; - -.default (@a: inherit) when (@a = inherit) { - content: default; -} -.default1 { .default } - -// true & false keywords -.test (@a) when (@a) { - content: "true."; -} -.test (@a) when not (@a) { - content: "false."; -} - -.test1 { .test(true) } -.test2 { .test(false) } -.test3 { .test(1) } -.test4 { .test(boo) } -.test5 { .test("true") } - -// Boolean expressions - -.bool () when (true) and (false) { content: true and false } // FALSE -.bool () when (true) and (true) { content: true and true } // TRUE -.bool () when (true) { content: true } // TRUE -.bool () when (false) and (false) { content: true } // FALSE -.bool () when (false), (true) { content: false, true } // TRUE -.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE -.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE -.bool () when (false), (true) and (true) { content: false, true and true } // TRUE -.bool () when (false), (false), (true) { content: false, false, true } // TRUE -.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE -.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE -.bool () when not (false) { content: not false } -.bool () when not (true) and not (false) { content: not true and not false } -.bool () when not (true) and not (true) { content: not true and not true } -.bool () when not (false) and (false), not (false) { content: not false and false, not false } - -.bool1 { .bool } - -.colorguard(@col) when (@col = red) { content: is @col; } -.colorguard(@col) when not (blue = @col) { content: is not blue its @col; } -.colorguard(@col) {} -.colorguardtest { - .colorguard(red); - .colorguard(blue); - .colorguard(purple); -} - -.stringguard(@str) when (@str = "theme1") { content: is theme1; } -.stringguard(@str) when not ("theme2" = @str) { content: is not theme2; } -.stringguard(@str) when (~"theme1" = @str) { content: is theme1 no quotes; } -.stringguard(@str) {} -.stringguardtest { - .stringguard("theme1"); - .stringguard("theme2"); - .stringguard(theme1); -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less deleted file mode 100644 index 790a4d6..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-important.less +++ /dev/null @@ -1,18 +0,0 @@ - -.mixin (9) { - border: 9 !important; -} -.mixin (@a: 0) { - border: @a; - boxer: @a; -} - -.class { - .mixin(1); - .mixin(2) !important; - .mixin(3); - .mixin(4) !important; - .mixin(5); - .mixin !important; - .mixin(9); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less deleted file mode 100644 index 57b07d0..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-named-args.less +++ /dev/null @@ -1,31 +0,0 @@ -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} -.mixin (@a: 1px, @b: 50%) when (@b > 75%){ - text-align: center; -} - -.named-arg { - color: blue; - .mixin(@b: 100%); -} - -.class { - @var: 20%; - .mixin(@b: @var); -} - -.mixin2 (@a: 1px, @b: 50%, @c: 50) { - width: @a * 5; - height: @b - 1%; - color: #000000 + @c; -} - -.named-args2 { - .mixin2(3px, @c: 100); -} - -.named-args3 { - .mixin2(@b: 30%, @c: #123456); -} \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less deleted file mode 100644 index d086279..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-nested.less +++ /dev/null @@ -1,22 +0,0 @@ -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} - -.class2 { - .mix(60); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less b/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less deleted file mode 100644 index b2121e9..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins-pattern.less +++ /dev/null @@ -1,99 +0,0 @@ -.mixin (...) { - variadic: true; -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/mixins.less b/enyo/tools/minifier/node_modules/less/test/less/mixins.less deleted file mode 100644 index 7158c2e..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/mixins.less +++ /dev/null @@ -1,93 +0,0 @@ -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} - -.bo, .bar { - width: 100%; -} -.bo { - border: 1px; -} -.ar.bo.ca { - color: black; -} -.jo.ki { - background: none; -} -.extended { - .bo; - .jo.ki; -} -.foo .bar { - .bar; -} -.has_parents() { - & .underParents { - color: red; - } -} -.has_parents(); -.parent { - .has_parents(); -} -.margin_between(@above, @below) { - * + & { margin-top: @above; } - legend + & { margin-top: 0; } - & + * { margin-top: @below; } -} -h1 { .margin_between(25px, 10px); } -h2 { .margin_between(20px, 8px); } -h3 { .margin_between(15px, 5px); } - -.mixin_def(@url, @position){ - background-image: @url; - background-position: @position; -} -.error{ - @s: "/"; - .mixin_def( "@{s}a.png", center center); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/operations.less b/enyo/tools/minifier/node_modules/less/test/less/operations.less deleted file mode 100644 index 46b0aa3..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/operations.less +++ /dev/null @@ -1,62 +0,0 @@ -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -.with-functions { - color: rgb(200, 200, 200) / 2; - color: 2 * hsl(0, 50%, 50%); - color: rgb(10, 10, 10) + hsl(0, 50%, 50%); -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.rem-dimensions { - font-size: 20rem / 5 + 1.5rem; // 5.5rem -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} - -.negations { - @var: 4px; - variable: -@var; // 4 - variable1: -@var + @var; // 0 - variable2: @var + -@var; // 0 - variable3: @var - -@var; // 8 - variable4: -@var - -@var; // 0 - paren: -(@var); // -4px - paren2: -(2 + 2) * -@var; // 16 -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/parens.less b/enyo/tools/minifier/node_modules/less/test/less/parens.less deleted file mode 100644 index e020c7e..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/parens.less +++ /dev/null @@ -1,26 +0,0 @@ -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/rulesets.less b/enyo/tools/minifier/node_modules/less/test/less/rulesets.less deleted file mode 100644 index e81192d..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/rulesets.less +++ /dev/null @@ -1,30 +0,0 @@ -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/scope.less b/enyo/tools/minifier/node_modules/less/test/less/scope.less deleted file mode 100644 index da66462..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/scope.less +++ /dev/null @@ -1,32 +0,0 @@ -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/selectors.less b/enyo/tools/minifier/node_modules/less/test/less/selectors.less deleted file mode 100644 index a66b598..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/selectors.less +++ /dev/null @@ -1,131 +0,0 @@ -h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} - -a { - color: red; - - &:hover { color: blue; } - - div & { color: green; } - - p & span { color: yellow; } -} - -.foo { - .bar, .baz { - & .qux { - display: block; - } - .qux & { - display: inline; - } - .qux& { - display: inline-block; - } - .qux & .biz { - display: none; - } - } -} - -.b { - &.c { - .a& { - color: red; - } - } -} - -.b { - .c & { - &.a { - color: red; - } - } -} - -.p { - .foo &.bar { - color: red; - } -} - -.p { - .foo&.bar { - color: red; - } -} - -.foo { - .foo + & { - background: amber; - } - & + & { - background: amber; - } -} - -.foo, .bar { - & + & { - background: amber; - } -} - -.foo, .bar { - a, b { - & > & { - background: amber; - } - } -} - -.other ::fnord { color: red } -.other::fnord { color: red } -.other { - ::bnord {color: red } - &::bnord {color: red } -} -// selector interpolation - deprecated -@theme: blood; -(~".@{theme}") { - color: red; -} -// selector interpolation - new format -@selector: ~".@{theme}"; -@{selector} { - color:red; -} -@{selector}red { - color: green; -} -.red { - #@{theme}.@{theme}&.black { - color:black; - } -} -@num: 3; -:nth-child(@{num}):nth-child(@num) { - second-use: deprecated; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/strings.less b/enyo/tools/minifier/node_modules/less/test/less/strings.less deleted file mode 100644 index 32fad72..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/strings.less +++ /dev/null @@ -1,51 +0,0 @@ -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; - escapes: "\"hello\" \\world"; - escapes2: "\"llo"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; - semi-colon: ';'; -} -#escaped { - filter: ~"DX.Transform.MS.BS.filter(opacity=50)"; -} -#one-line { image: url(http://tooks.com) } -#crazy { image: url(http://), "}", url("http://}") } -#interpolation { - @var: '/dev'; - url: "http://lesscss.org@{var}/image.jpg"; - - @var2: 256; - url2: "http://lesscss.org/image-@{var2}.jpg"; - - @var3: #456; - url3: "http://lesscss.org@{var3}"; - - @var4: hello; - url4: "http://lesscss.org/@{var4}"; - - @var5: 54.4px; - url5: "http://lesscss.org/@{var5}"; -} - -// multiple calls with string interpolation - -.mix-mul (@a: green) { - color: ~"@{a}"; -} -.mix-mul-class { - .mix-mul(blue); - .mix-mul(red); - .mix-mul(black); - .mix-mul(orange); -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/variables.less b/enyo/tools/minifier/node_modules/less/test/less/variables.less deleted file mode 100644 index 66ab4ef..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/variables.less +++ /dev/null @@ -1,54 +0,0 @@ -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - @multi: 'A', B, C; - font-family: @a, @a, @a; - color: @c !important; - url: url(@a); - multi: something @multi, @a; -} - -.variable-names { - @var: 'hello'; - @name: 'var'; - name: @@name; -} -.alpha { - @var: 42; - filter: alpha(opacity=@var); -} - -a:nth-child(@a) { - border: 1px; -} diff --git a/enyo/tools/minifier/node_modules/less/test/less/whitespace.less b/enyo/tools/minifier/node_modules/less/test/less/whitespace.less deleted file mode 100644 index ab4804d..0000000 --- a/enyo/tools/minifier/node_modules/less/test/less/whitespace.less +++ /dev/null @@ -1,44 +0,0 @@ - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} -.sel -.newline_ws .tab_ws { -color: -white; -background-position: 45 --23; -} diff --git a/enyo/tools/minifier/node_modules/uglify-js/.npmignore b/enyo/tools/minifier/node_modules/uglify-js/.npmignore deleted file mode 100644 index 83c3dac..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.DS_Store -.tmp*~ -*.local.* -.pinf-* -node_modules/ -npm-debug.log diff --git a/enyo/tools/minifier/node_modules/uglify-js/README.html b/enyo/tools/minifier/node_modules/uglify-js/README.html deleted file mode 100644 index 5f37ac0..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/README.html +++ /dev/null @@ -1,981 +0,0 @@ - - - - -UglifyJS – a JavaScript parser/compressor/beautifier - - - - - - - - - - - - - -
    - -
    - -
    -

    UglifyJS – a JavaScript parser/compressor/beautifier

    - - - - -
    -

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    -
    - - -

    -This package implements a general-purpose JavaScript -parser/compressor/beautifier toolkit. It is developed on NodeJS, but it -should work on any JavaScript platform supporting the CommonJS module system -(and if your platform of choice doesn't support CommonJS, you can easily -implement it, or discard the exports.* lines from UglifyJS sources). -

    -

    -The tokenizer/parser generates an abstract syntax tree from JS code. You -can then traverse the AST to learn more about the code, or do various -manipulations on it. This part is implemented in parse-js.js and it's a -port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. -

    -

    -( See cl-uglify-js if you're looking for the Common Lisp version of -UglifyJS. ) -

    -

    -The second part of this package, implemented in process.js, inspects and -manipulates the AST generated by the parser to provide the following: -

    -
      -
    • ability to re-generate JavaScript code from the AST. Optionally - indented—you can use this if you want to “beautify” a program that has - been compressed, so that you can inspect the source. But you can also run - our code generator to print out an AST without any whitespace, so you - achieve compression as well. - -
    • -
    • shorten variable names (usually to single characters). Our mangler will - analyze the code and generate proper variable names, depending on scope - and usage, and is smart enough to deal with globals defined elsewhere, or - with eval() calls or with{} statements. In short, if eval() or - with{} are used in some scope, then all variables in that scope and any - variables in the parent scopes will remain unmangled, and any references - to such variables remain unmangled as well. - -
    • -
    • various small optimizations that may lead to faster code but certainly - lead to smaller code. Where possible, we do the following: - -
        -
      • foo["bar"] ==> foo.bar - -
      • -
      • remove block brackets {} - -
      • -
      • join consecutive var declarations: - var a = 10; var b = 20; ==> var a=10,b=20; - -
      • -
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the - replacement if the result occupies less bytes; for example 1/3 would - translate to 0.333333333333, so in this case we don't replace it. - -
      • -
      • consecutive statements in blocks are merged into a sequence; in many - cases, this leaves blocks with a single statement, so then we can remove - the block brackets. - -
      • -
      • various optimizations for IF statements: - -
          -
        • if (foo) bar(); else baz(); ==> foo?bar():baz(); -
        • -
        • if (!foo) bar(); else baz(); ==> foo?baz():bar(); -
        • -
        • if (foo) bar(); ==> foo&&bar(); -
        • -
        • if (!foo) bar(); ==> foo||bar(); -
        • -
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); -
        • -
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} - -
        • -
        - -
      • -
      • remove some unreachable code and warn about it (code that follows a - return, throw, break or continue statement, except - function/variable declarations). - -
      • -
      • act a limited version of a pre-processor (c.f. the pre-processor of - C/C++) to allow you to safely replace selected global symbols with - specified values. When combined with the optimisations above this can - make UglifyJS operate slightly more like a compilation process, in - that when certain symbols are replaced by constant values, entire code - blocks may be optimised away as unreachable. -
      • -
      - -
    • -
    - - - -
    - -
    -

    1.1 Unsafe transformations

    -
    - - -

    -The following transformations can in theory break code, although they're -probably safe in most practical cases. To enable them you need to pass the ---unsafe flag. -

    - -
    - -
    -

    1.1.1 Calls involving the global Array constructor

    -
    - - -

    -The following transformations occur: -

    - - - -
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    -Array(a, b, c)         => [a,b,c]
    -new Array(5)           => Array(5)
    -new Array(a)           => Array(a)
    -
    - - -

    -These are all safe if the Array name isn't redefined. JavaScript does allow -one to globally redefine Array (and pretty much everything, in fact) but I -personally don't see why would anyone do that. -

    -

    -UglifyJS does handle the case where Array is redefined locally, or even -globally but with a function or var declaration. Therefore, in the -following cases UglifyJS doesn't touch calls or instantiations of Array: -

    - - - -
    // case 1.  globally declared variable
    -  var Array;
    -  new Array(1, 2, 3);
    -  Array(a, b);
    -
    -  // or (can be declared later)
    -  new Array(1, 2, 3);
    -  var Array;
    -
    -  // or (can be a function)
    -  new Array(1, 2, 3);
    -  function Array() { ... }
    -
    -// case 2.  declared in a function
    -  (function(){
    -    a = new Array(1, 2, 3);
    -    b = Array(5, 6);
    -    var Array;
    -  })();
    -
    -  // or
    -  (function(Array){
    -    return Array(5, 6, 7);
    -  })();
    -
    -  // or
    -  (function(){
    -    return new Array(1, 2, 3, 4);
    -    function Array() { ... }
    -  })();
    -
    -  // etc.
    -
    - - -
    - -
    - -
    -

    1.1.2 obj.toString() ==> obj+“”

    -
    - - -
    -
    - -
    - -
    -

    1.2 Install (NPM)

    -
    - - -

    -UglifyJS is now available through NPM — npm install uglify-js should do -the job. -

    -
    - -
    - -
    -

    1.3 Install latest code from GitHub

    -
    - - - - - -
    ## clone the repository
    -mkdir -p /where/you/wanna/put/it
    -cd /where/you/wanna/put/it
    -git clone git://github.com/mishoo/UglifyJS.git
    -
    -## make the module available to Node
    -mkdir -p ~/.node_libraries/
    -cd ~/.node_libraries/
    -ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
    -
    -## and if you want the CLI script too:
    -mkdir -p ~/bin
    -cd ~/bin
    -ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
    -  # (then add ~/bin to your $PATH if it's not there already)
    -
    - - -
    - -
    - -
    -

    1.4 Usage

    -
    - - -

    -There is a command-line tool that exposes the functionality of this library -for your shell-scripting needs: -

    - - - -
    uglifyjs [ options... ] [ filename ]
    -
    - - -

    -filename should be the last argument and should name the file from which -to read the JavaScript code. If you don't specify it, it will read code -from STDIN. -

    -

    -Supported options: -

    -
      -
    • -b or --beautify — output indented code; when passed, additional - options control the beautifier: - -
        -
      • -i N or --indent N — indentation level (number of spaces) - -
      • -
      • -q or --quote-keys — quote keys in literal objects (by default, - only keys that cannot be identifier names will be quotes). - -
      • -
      - -
    • -
    • --ascii — pass this argument to encode non-ASCII characters as - \uXXXX sequences. By default UglifyJS won't bother to do it and will - output Unicode characters instead. (the output is always encoded in UTF8, - but if you pass this option you'll only get ASCII). - -
    • -
    • -nm or --no-mangle — don't mangle names. - -
    • -
    • -nmf or --no-mangle-functions – in case you want to mangle variable - names, but not touch function names. - -
    • -
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various - optimizations that result in smaller, less readable code). - -
    • -
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too - (by default we don't do this). - -
    • -
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass - --no-squeeze) it will reduce consecutive statements in blocks into a - sequence. For example, "a = 10; b = 20; foo();" will be written as - "a=10,b=20,foo();". In various occasions, this allows us to discard the - block brackets (since the block becomes a single statement). This is ON - by default because it seems safe and saves a few hundred bytes on some - libs that I tested it on, but pass --no-seqs to disable it. - -
    • -
    • --no-dead-code — by default, UglifyJS will remove code that is - obviously unreachable (code that follows a return, throw, break or - continue statement and is not a function/variable declaration). Pass - this option to disable this optimization. - -
    • -
    • -nc or --no-copyright — by default, uglifyjs will keep the initial - comment tokens in the generated code (assumed to be copyright information - etc.). If you pass this it will discard it. - -
    • -
    • -o filename or --output filename — put the result in filename. If - this isn't given, the result goes to standard output (or see next one). - -
    • -
    • --overwrite — if the code is read from a file (not from STDIN) and you - pass --overwrite then the output will be written in the same file. - -
    • -
    • --ast — pass this if you want to get the Abstract Syntax Tree instead - of JavaScript as output. Useful for debugging or learning more about the - internals. - -
    • -
    • -v or --verbose — output some notes on STDERR (for now just how long - each operation takes). - -
    • -
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace - all instances of the specified symbol where used as an identifier - (except where symbol has properly declared by a var declaration or - use as function parameter or similar) with the specified value. This - argument may be specified multiple times to define multiple - symbols - if no value is specified the symbol will be replaced with - the value true, or you can specify a numeric value (such as - 1024), a quoted string value (such as ="object"= or - ='https://github.com'), or the name of another symbol or keyword (such as =null or document). - This allows you, for example, to assign meaningful names to key - constant values but discard the symbolic names in the uglified - version for brevity/efficiency, or when used wth care, allows - UglifyJS to operate as a form of conditional compilation - whereby defining appropriate values may, by dint of the constant - folding and dead code removal features above, remove entire - superfluous code blocks (e.g. completely remove instrumentation or - trace code for production use). - Where string values are being defined, the handling of quotes are - likely to be subject to the specifics of your command shell - environment, so you may need to experiment with quoting styles - depending on your platform, or you may find the option - --define-from-module more suitable for use. - -
    • -
    • -define-from-module SOMEMODULE — will load the named module (as - per the NodeJS require() function) and iterate all the exported - properties of the module defining them as symbol names to be defined - (as if by the --define option) per the name of each property - (i.e. without the module name prefix) and given the value of the - property. This is a much easier way to handle and document groups of - symbols to be defined rather than a large number of --define - options. - -
    • -
    • --unsafe — enable other additional optimizations that are known to be - unsafe in some contrived situations, but could still be generally useful. - For now only these: - -
        -
      • foo.toString() ==> foo+"" -
      • -
      • new Array(x,…) ==> [x,…] -
      • -
      • new Array(x) ==> Array(x) - -
      • -
      - -
    • -
    • --max-line-len (default 32K characters) — add a newline after around - 32K characters. I've seen both FF and Chrome croak when all the code was - on a single line of around 670K. Pass –max-line-len 0 to disable this - safety feature. - -
    • -
    • --reserved-names — some libraries rely on certain names to be used, as - pointed out in issue #92 and #81, so this option allow you to exclude such - names from the mangler. For example, to keep names require and $super - intact you'd specify –reserved-names "require,$super". - -
    • -
    • --inline-script – when you want to include the output literally in an - HTML <script> tag you can use this option to prevent </script from - showing up in the output. - -
    • -
    • --lift-vars – when you pass this, UglifyJS will apply the following - transformations (see the notes in API, ast_lift_variables): - -
        -
      • put all var declarations at the start of the scope -
      • -
      • make sure a variable is declared only once -
      • -
      • discard unused function arguments -
      • -
      • discard unused inner (named) functions -
      • -
      • finally, try to merge assignments into that one var declaration, if - possible. -
      • -
      - -
    • -
    - - - -
    - -
    -

    1.4.1 API

    -
    - - -

    -To use the library from JavaScript, you'd do the following (example for -NodeJS): -

    - - - -
    var jsp = require("uglify-js").parser;
    -var pro = require("uglify-js").uglify;
    -
    -var orig_code = "... JS code here";
    -var ast = jsp.parse(orig_code); // parse code and get the initial AST
    -ast = pro.ast_mangle(ast); // get a new AST with mangled names
    -ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    -var final_code = pro.gen_code(ast); // compressed code here
    -
    - - -

    -The above performs the full compression that is possible right now. As you -can see, there are a sequence of steps which you can apply. For example if -you want compressed output but for some reason you don't want to mangle -variable names, you would simply skip the line that calls -pro.ast_mangle(ast). -

    -

    -Some of these functions take optional arguments. Here's a description: -

    -
      -
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. - strict_semicolons is optional and defaults to false. If you pass - true then the parser will throw an error when it expects a semicolon and - it doesn't find it. For most JS code you don't want that, but it's useful - if you want to strictly sanitize your code. - -
    • -
    • pro.ast_lift_variables(ast) – merge and move var declarations to the - scop of the scope; discard unused function arguments or variables; discard - unused (named) inner functions. It also tries to merge assignments - following the var declaration into it. - -

      - If your code is very hand-optimized concerning var declarations, this - lifting variable declarations might actually increase size. For me it - helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also - note that (since it's not enabled by default) this operation isn't yet - heavily tested (please report if you find issues!). -

      -

      - Note that although it might increase the image size (on jQuery it gains - 865 bytes, 243 after gzip) it's technically more correct: in certain - situations, dead code removal might drop variable declarations, which - would not happen if the variables are lifted in advance. -

      -

      - Here's an example of what it does: -

    • -
    - - - - - -
    function f(a, b, c, d, e) {
    -    var q;
    -    var w;
    -    w = 10;
    -    q = 20;
    -    for (var i = 1; i < 10; ++i) {
    -        var boo = foo(a);
    -    }
    -    for (var i = 0; i < 1; ++i) {
    -        var boo = bar(c);
    -    }
    -    function foo(){ ... }
    -    function bar(){ ... }
    -    function baz(){ ... }
    -}
    -
    -// transforms into ==>
    -
    -function f(a, b, c) {
    -    var i, boo, w = 10, q = 20;
    -    for (i = 1; i < 10; ++i) {
    -        boo = foo(a);
    -    }
    -    for (i = 0; i < 1; ++i) {
    -        boo = bar(c);
    -    }
    -    function foo() { ... }
    -    function bar() { ... }
    -}
    -
    - - -
      -
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled - (compressed) variable and function names. It supports the following - options: - -
        -
      • toplevel – mangle toplevel names (by default we don't touch them). -
      • -
      • except – an array of names to exclude from compression. -
      • -
      • defines – an object with properties named after symbols to - replace (see the --define option for the script) and the values - representing the AST replacement value. - -
      • -
      - -
    • -
    • pro.ast_squeeze(ast, options) – employs further optimizations designed - to reduce the size of the code that gen_code would generate from the - AST. Returns a new AST. options can be a hash; the supported options - are: - -
        -
      • make_seqs (default true) which will cause consecutive statements in a - block to be merged using the "sequence" (comma) operator - -
      • -
      • dead_code (default true) which will remove unreachable code. - -
      • -
      - -
    • -
    • pro.gen_code(ast, options) – generates JS code from the AST. By - default it's minified, but using the options argument you can get nicely - formatted output. options is, well, optional :-) and if you pass it it - must be an object and supports the following properties (below you can see - the default values): - -
        -
      • beautify: false – pass true if you want indented output -
      • -
      • indent_start: 0 (only applies when beautify is true) – initial - indentation in spaces -
      • -
      • indent_level: 4 (only applies when beautify is true) -- - indentation level, in spaces (pass an even number) -
      • -
      • quote_keys: false – if you pass true it will quote all keys in - literal objects -
      • -
      • space_colon: false (only applies when beautify is true) – wether - to put a space before the colon in object literals -
      • -
      • ascii_only: false – pass true if you want to encode non-ASCII - characters as \uXXXX. -
      • -
      • inline_script: false – pass true to escape occurrences of - </script in strings -
      • -
      - -
    • -
    - - -
    - -
    - -
    -

    1.4.2 Beautifier shortcoming – no more comments

    -
    - - -

    -The beautifier can be used as a general purpose indentation tool. It's -useful when you want to make a minified file readable. One limitation, -though, is that it discards all comments, so you don't really want to use it -to reformat your code, unless you don't have, or don't care about, comments. -

    -

    -In fact it's not the beautifier who discards comments — they are dumped at -the parsing stage, when we build the initial AST. Comments don't really -make sense in the AST, and while we could add nodes for them, it would be -inconvenient because we'd have to add special rules to ignore them at all -the processing stages. -

    -
    - -
    - -
    -

    1.4.3 Use as a code pre-processor

    -
    - - -

    -The --define option can be used, particularly when combined with the -constant folding logic, as a form of pre-processor to enable or remove -particular constructions, such as might be used for instrumenting -development code, or to produce variations aimed at a specific -platform. -

    -

    -The code below illustrates the way this can be done, and how the -symbol replacement is performed. -

    - - - -
    CLAUSE1: if (typeof DEVMODE === 'undefined') {
    -    DEVMODE = true;
    -}
    -
    -CLAUSE2: function init() {
    -    if (DEVMODE) {
    -        console.log("init() called");
    -    }
    -    ....
    -    DEVMODE &amp;&amp; console.log("init() complete");
    -}
    -
    -CLAUSE3: function reportDeviceStatus(device) {
    -    var DEVMODE = device.mode, DEVNAME = device.name;
    -    if (DEVMODE === 'open') {
    -        ....
    -    }
    -}
    -
    - - -

    -When the above code is normally executed, the undeclared global -variable DEVMODE will be assigned the value true (see CLAUSE1) -and so the init() function (CLAUSE2) will write messages to the -console log when executed, but in CLAUSE3 a locally declared -variable will mask access to the DEVMODE global symbol. -

    -

    -If the above code is processed by UglifyJS with an argument of ---define DEVMODE=false then UglifyJS will replace DEVMODE with the -boolean constant value false within CLAUSE1 and CLAUSE2, but it -will leave CLAUSE3 as it stands because there DEVMODE resolves to -a validly declared variable. -

    -

    -And more so, the constant-folding features of UglifyJS will recognise -that the if condition of CLAUSE1 is thus always false, and so will -remove the test and body of CLAUSE1 altogether (including the -otherwise slightly problematical statement false = true; which it -will have formed by replacing DEVMODE in the body). Similarly, -within CLAUSE2 both calls to console.log() will be removed -altogether. -

    -

    -In this way you can mimic, to a limited degree, the functionality of -the C/C++ pre-processor to enable or completely remove blocks -depending on how certain symbols are defined - perhaps using UglifyJS -to generate different versions of source aimed at different -environments -

    -

    -It is recommmended (but not made mandatory) that symbols designed for -this purpose are given names consisting of UPPER_CASE_LETTERS to -distinguish them from other (normal) symbols and avoid the sort of -clash that CLAUSE3 above illustrates. -

    -
    -
    - -
    - -
    -

    1.5 Compression – how good is it?

    -
    - - -

    -Here are updated statistics. (I also updated my Google Closure and YUI -installations). -

    -

    -We're still a lot better than YUI in terms of compression, though slightly -slower. We're still a lot faster than Closure, and compression after gzip -is comparable. -

    - - -- - - - - - - - - - -
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    - - -
    - -
    - -
    -

    1.6 Bugs?

    -
    - - -

    -Unfortunately, for the time being there is no automated test suite. But I -ran the compressor manually on non-trivial code, and then I tested that the -generated code works as expected. A few hundred times. -

    -

    -DynarchLIB was started in times when there was no good JS minifier. -Therefore I was quite religious about trying to write short code manually, -and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a -= 10 : b = 20”, though the more readable version would clearly be to use -“if/else”. -

    -

    -Since the parser/compressor runs fine on DL and jQuery, I'm quite confident -that it's solid enough for production use. If you can identify any bugs, -I'd love to hear about them (use the Google Group or email me directly). -

    -
    - -
    - -
    -

    1.7 Links

    -
    - - - - - -
    - -
    - -
    -

    1.8 License

    -
    - - -

    -UglifyJS is released under the BSD license: -

    - - - -
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    -Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    -
    -Redistribution and use in source and binary forms, with or without
    -modification, are permitted provided that the following conditions
    -are met:
    -
    -    * Redistributions of source code must retain the above
    -      copyright notice, this list of conditions and the following
    -      disclaimer.
    -
    -    * Redistributions in binary form must reproduce the above
    -      copyright notice, this list of conditions and the following
    -      disclaimer in the documentation and/or other materials
    -      provided with the distribution.
    -
    -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    -SUCH DAMAGE.
    -
    - - -
    -

    Footnotes:

    -
    -

    1 I even reported a few bugs and suggested some fixes in the original - parse-js library, and Marijn pushed fixes literally in minutes. -

    -
    -
    - -
    -
    -
    - -
    -

    Date: 2011-12-09 14:59:08 EET

    -

    Author: Mihai Bazon

    -

    Org version 7.7 with Emacs version 23

    -Validate XHTML 1.0 - -
    - - diff --git a/enyo/tools/minifier/node_modules/uglify-js/README.org b/enyo/tools/minifier/node_modules/uglify-js/README.org deleted file mode 100644 index d36b6b2..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/README.org +++ /dev/null @@ -1,578 +0,0 @@ -#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier -#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier -#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript -#+STYLE: -#+AUTHOR: Mihai Bazon -#+EMAIL: mihai.bazon@gmail.com - -* UglifyJS --- a JavaScript parser/compressor/beautifier - -This package implements a general-purpose JavaScript -parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it -should work on any JavaScript platform supporting the CommonJS module system -(and if your platform of choice doesn't support CommonJS, you can easily -implement it, or discard the =exports.*= lines from UglifyJS sources). - -The tokenizer/parser generates an abstract syntax tree from JS code. You -can then traverse the AST to learn more about the code, or do various -manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a -port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn -Haverbeke]]. - -( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of -UglifyJS. ) - -The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and -manipulates the AST generated by the parser to provide the following: - -- ability to re-generate JavaScript code from the AST. Optionally - indented---you can use this if you want to “beautify” a program that has - been compressed, so that you can inspect the source. But you can also run - our code generator to print out an AST without any whitespace, so you - achieve compression as well. - -- shorten variable names (usually to single characters). Our mangler will - analyze the code and generate proper variable names, depending on scope - and usage, and is smart enough to deal with globals defined elsewhere, or - with =eval()= calls or =with{}= statements. In short, if =eval()= or - =with{}= are used in some scope, then all variables in that scope and any - variables in the parent scopes will remain unmangled, and any references - to such variables remain unmangled as well. - -- various small optimizations that may lead to faster code but certainly - lead to smaller code. Where possible, we do the following: - - - foo["bar"] ==> foo.bar - - - remove block brackets ={}= - - - join consecutive var declarations: - var a = 10; var b = 20; ==> var a=10,b=20; - - - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the - replacement if the result occupies less bytes; for example 1/3 would - translate to 0.333333333333, so in this case we don't replace it. - - - consecutive statements in blocks are merged into a sequence; in many - cases, this leaves blocks with a single statement, so then we can remove - the block brackets. - - - various optimizations for IF statements: - - - if (foo) bar(); else baz(); ==> foo?bar():baz(); - - if (!foo) bar(); else baz(); ==> foo?baz():bar(); - - if (foo) bar(); ==> foo&&bar(); - - if (!foo) bar(); ==> foo||bar(); - - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); - - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} - - - remove some unreachable code and warn about it (code that follows a - =return=, =throw=, =break= or =continue= statement, except - function/variable declarations). - - - act a limited version of a pre-processor (c.f. the pre-processor of - C/C++) to allow you to safely replace selected global symbols with - specified values. When combined with the optimisations above this can - make UglifyJS operate slightly more like a compilation process, in - that when certain symbols are replaced by constant values, entire code - blocks may be optimised away as unreachable. - -** <> - -The following transformations can in theory break code, although they're -probably safe in most practical cases. To enable them you need to pass the -=--unsafe= flag. - -*** Calls involving the global Array constructor - -The following transformations occur: - -#+BEGIN_SRC js -new Array(1, 2, 3, 4) => [1,2,3,4] -Array(a, b, c) => [a,b,c] -new Array(5) => Array(5) -new Array(a) => Array(a) -#+END_SRC - -These are all safe if the Array name isn't redefined. JavaScript does allow -one to globally redefine Array (and pretty much everything, in fact) but I -personally don't see why would anyone do that. - -UglifyJS does handle the case where Array is redefined locally, or even -globally but with a =function= or =var= declaration. Therefore, in the -following cases UglifyJS *doesn't touch* calls or instantiations of Array: - -#+BEGIN_SRC js -// case 1. globally declared variable - var Array; - new Array(1, 2, 3); - Array(a, b); - - // or (can be declared later) - new Array(1, 2, 3); - var Array; - - // or (can be a function) - new Array(1, 2, 3); - function Array() { ... } - -// case 2. declared in a function - (function(){ - a = new Array(1, 2, 3); - b = Array(5, 6); - var Array; - })(); - - // or - (function(Array){ - return Array(5, 6, 7); - })(); - - // or - (function(){ - return new Array(1, 2, 3, 4); - function Array() { ... } - })(); - - // etc. -#+END_SRC - -*** =obj.toString()= ==> =obj+“”= - -** Install (NPM) - -UglifyJS is now available through NPM --- =npm install uglify-js= should do -the job. - -** Install latest code from GitHub - -#+BEGIN_SRC sh -## clone the repository -mkdir -p /where/you/wanna/put/it -cd /where/you/wanna/put/it -git clone git://github.com/mishoo/UglifyJS.git - -## make the module available to Node -mkdir -p ~/.node_libraries/ -cd ~/.node_libraries/ -ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js - -## and if you want the CLI script too: -mkdir -p ~/bin -cd ~/bin -ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs - # (then add ~/bin to your $PATH if it's not there already) -#+END_SRC - -** Usage - -There is a command-line tool that exposes the functionality of this library -for your shell-scripting needs: - -#+BEGIN_SRC sh -uglifyjs [ options... ] [ filename ] -#+END_SRC - -=filename= should be the last argument and should name the file from which -to read the JavaScript code. If you don't specify it, it will read code -from STDIN. - -Supported options: - -- =-b= or =--beautify= --- output indented code; when passed, additional - options control the beautifier: - - - =-i N= or =--indent N= --- indentation level (number of spaces) - - - =-q= or =--quote-keys= --- quote keys in literal objects (by default, - only keys that cannot be identifier names will be quotes). - -- =-c= or =----consolidate-primitive-values= --- consolidates null, Boolean, - and String values. Known as aliasing in the Closure Compiler. Worsens the - data compression ratio of gzip. - -- =--ascii= --- pass this argument to encode non-ASCII characters as - =\uXXXX= sequences. By default UglifyJS won't bother to do it and will - output Unicode characters instead. (the output is always encoded in UTF8, - but if you pass this option you'll only get ASCII). - -- =-nm= or =--no-mangle= --- don't mangle names. - -- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable - names, but not touch function names. - -- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various - optimizations that result in smaller, less readable code). - -- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too - (by default we don't do this). - -- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass - =--no-squeeze=) it will reduce consecutive statements in blocks into a - sequence. For example, "a = 10; b = 20; foo();" will be written as - "a=10,b=20,foo();". In various occasions, this allows us to discard the - block brackets (since the block becomes a single statement). This is ON - by default because it seems safe and saves a few hundred bytes on some - libs that I tested it on, but pass =--no-seqs= to disable it. - -- =--no-dead-code= --- by default, UglifyJS will remove code that is - obviously unreachable (code that follows a =return=, =throw=, =break= or - =continue= statement and is not a function/variable declaration). Pass - this option to disable this optimization. - -- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial - comment tokens in the generated code (assumed to be copyright information - etc.). If you pass this it will discard it. - -- =-o filename= or =--output filename= --- put the result in =filename=. If - this isn't given, the result goes to standard output (or see next one). - -- =--overwrite= --- if the code is read from a file (not from STDIN) and you - pass =--overwrite= then the output will be written in the same file. - -- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead - of JavaScript as output. Useful for debugging or learning more about the - internals. - -- =-v= or =--verbose= --- output some notes on STDERR (for now just how long - each operation takes). - -- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace - all instances of the specified symbol where used as an identifier - (except where symbol has properly declared by a var declaration or - use as function parameter or similar) with the specified value. This - argument may be specified multiple times to define multiple - symbols - if no value is specified the symbol will be replaced with - the value =true=, or you can specify a numeric value (such as - =1024=), a quoted string value (such as ="object"= or - ='https://github.com'=), or the name of another symbol or keyword - (such as =null= or =document=). - This allows you, for example, to assign meaningful names to key - constant values but discard the symbolic names in the uglified - version for brevity/efficiency, or when used wth care, allows - UglifyJS to operate as a form of *conditional compilation* - whereby defining appropriate values may, by dint of the constant - folding and dead code removal features above, remove entire - superfluous code blocks (e.g. completely remove instrumentation or - trace code for production use). - Where string values are being defined, the handling of quotes are - likely to be subject to the specifics of your command shell - environment, so you may need to experiment with quoting styles - depending on your platform, or you may find the option - =--define-from-module= more suitable for use. - -- =-define-from-module SOMEMODULE= --- will load the named module (as - per the NodeJS =require()= function) and iterate all the exported - properties of the module defining them as symbol names to be defined - (as if by the =--define= option) per the name of each property - (i.e. without the module name prefix) and given the value of the - property. This is a much easier way to handle and document groups of - symbols to be defined rather than a large number of =--define= - options. - -- =--unsafe= --- enable other additional optimizations that are known to be - unsafe in some contrived situations, but could still be generally useful. - For now only these: - - - foo.toString() ==> foo+"" - - new Array(x,...) ==> [x,...] - - new Array(x) ==> Array(x) - -- =--max-line-len= (default 32K characters) --- add a newline after around - 32K characters. I've seen both FF and Chrome croak when all the code was - on a single line of around 670K. Pass --max-line-len 0 to disable this - safety feature. - -- =--reserved-names= --- some libraries rely on certain names to be used, as - pointed out in issue #92 and #81, so this option allow you to exclude such - names from the mangler. For example, to keep names =require= and =$super= - intact you'd specify --reserved-names "require,$super". - -- =--inline-script= -- when you want to include the output literally in an - HTML =\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    1.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.1.2 obj.toString() ==> obj+“”

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    1.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    1.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    1.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    1.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    1.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    1.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    1.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2011-12-09 14:59:08 EET

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", - "_id": "uglify-js@1.3.2", - "dist": { - "shasum": "0f36c685d58468a2a35945eaaa5f32a3fda555d8" - }, - "_from": "uglify-js@1.3.2" -} diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js b/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js deleted file mode 100644 index f19369e..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/beautify.js +++ /dev/null @@ -1,28 +0,0 @@ -#! /usr/bin/env node - -global.sys = require("sys"); -var fs = require("fs"); - -var jsp = require("../lib/parse-js"); -var pro = require("../lib/process"); - -var filename = process.argv[2]; -fs.readFile(filename, "utf8", function(err, text){ - try { - var ast = time_it("parse", function(){ return jsp.parse(text); }); - ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); - ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); - var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); - sys.puts(gen); - } catch(ex) { - sys.debug(ex.stack); - sys.debug(sys.inspect(ex)); - sys.debug(JSON.stringify(ex)); - } -}); - -function time_it(name, cont) { - var t1 = new Date().getTime(); - try { return cont(); } - finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } -}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js b/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js deleted file mode 100644 index 14a8002..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/testparser.js +++ /dev/null @@ -1,409 +0,0 @@ -#! /usr/bin/env node -global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; - -var parseJS = require("../lib/parse-js"); -var sys = require("sys"); - -// write debug in a very straightforward manner -var debug = function(){ - sys.log(Array.prototype.slice.call(arguments).join(', ')); -}; - -var testsPassed = true; - -ParserTestSuite(function(i, input, desc){ - try { - parseJS.parse(input); - debug("ok " + i + ": " + desc); - } catch(e){ - debug("FAIL " + i + " " + desc + " (" + e + ")"); - testsPassed = false; - } -}); - -process.exit(testsPassed ? 0 : 1); - -function ParserTestSuite(callback){ - var inps = [ - ["var abc;", "Regular variable statement w/o assignment"], - ["var abc = 5;", "Regular variable statement with assignment"], - ["/* */;", "Multiline comment"], - ['/** **/;', 'Double star multiline comment'], - ["var f = function(){;};", "Function expression in var assignment"], - ['hi; // moo\n;', 'single line comment'], - ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) - ['a + b;', 'addition'], - ["'a';", 'single string literal'], - ["'a\\n';", 'single string literal with escaped return'], - ['"a";', 'double string literal'], - ['"a\\n";', 'double string literal with escaped return'], - ['"var";', 'string is a keyword'], - ['"variable";', 'string starts with a keyword'], - ['"somevariable";', 'string contains a keyword'], - ['"somevar";', 'string ends with a keyword'], - ['500;', 'int literal'], - ['500.;', 'float literal w/o decimals'], - ['500.432;', 'float literal with decimals'], - ['.432432;', 'float literal w/o int'], - ['(a,b,c);', 'parens and comma'], - ['[1,2,abc];', 'array literal'], - ['var o = {a:1};', 'object literal unquoted key'], - ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... - ['var o = {c:c};', 'object literal keyname is identifier'], - ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], - ['var x;\nvar y;', 'two lines'], - ['var x;\nfunction n(){; }', 'function def'], - ['var x;\nfunction n(abc){; }', 'function def with arg'], - ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], - ['function n(){ "hello"; }', 'function def with body'], - ['/a/;', 'regex literal'], - ['/a/b;', 'regex literal with flag'], - ['/a/ / /b/;', 'regex div regex'], - ['a/b/c;', 'triple division looks like regex'], - ['+function(){/regex/;};', 'regex at start of function body'], - // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 - // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 - - // first tests for the lexer, should also parse as program (when you append a semi) - - // comments - ['//foo!@#^&$1234\nbar;', 'single line comment'], - ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], - ['/*foo\nbar*/;','multi line comment'], - ['/*x*x*/;','multi line comment with *'], - ['/**/;','empty comment'], - // identifiers - ["x;",'1 identifier'], - ["_x;",'2 identifier'], - ["xyz;",'3 identifier'], - ["$x;",'4 identifier'], - ["x$;",'5 identifier'], - ["_;",'6 identifier'], - ["x5;",'7 identifier'], - ["x_y;",'8 identifier'], - ["x+5;",'9 identifier'], - ["xyz123;",'10 identifier'], - ["x1y1z1;",'11 identifier'], - ["foo\\u00D8bar;",'12 identifier unicode escape'], - //["foo�bar;",'13 identifier unicode embedded (might fail)'], - // numbers - ["5;", '1 number'], - ["5.5;", '2 number'], - ["0;", '3 number'], - ["0.0;", '4 number'], - ["0.001;", '5 number'], - ["1.e2;", '6 number'], - ["1.e-2;", '7 number'], - ["1.E2;", '8 number'], - ["1.E-2;", '9 number'], - [".5;", '10 number'], - [".5e3;", '11 number'], - [".5e-3;", '12 number'], - ["0.5e3;", '13 number'], - ["55;", '14 number'], - ["123;", '15 number'], - ["55.55;", '16 number'], - ["55.55e10;", '17 number'], - ["123.456;", '18 number'], - ["1+e;", '20 number'], - ["0x01;", '22 number'], - ["0XCAFE;", '23 number'], - ["0x12345678;", '24 number'], - ["0x1234ABCD;", '25 number'], - ["0x0001;", '26 number'], - // strings - ["\"foo\";", '1 string'], - ["\'foo\';", '2 string'], - ["\"x\";", '3 string'], - ["\'\';", '4 string'], - ["\"foo\\tbar\";", '5 string'], - ["\"!@#$%^&*()_+{}[]\";", '6 string'], - ["\"/*test*/\";", '7 string'], - ["\"//test\";", '8 string'], - ["\"\\\\\";", '9 string'], - ["\"\\u0001\";", '10 string'], - ["\"\\uFEFF\";", '11 string'], - ["\"\\u10002\";", '12 string'], - ["\"\\x55\";", '13 string'], - ["\"\\x55a\";", '14 string'], - ["\"a\\\\nb\";", '15 string'], - ['";"', '16 string: semi in a string'], - ['"a\\\nb";', '17 string: line terminator escape'], - // literals - ["null;", "null"], - ["true;", "true"], - ["false;", "false"], - // regex - ["/a/;", "1 regex"], - ["/abc/;", "2 regex"], - ["/abc[a-z]*def/g;", "3 regex"], - ["/\\b/;", "4 regex"], - ["/[a-zA-Z]/;", "5 regex"], - - // program tests (for as far as they havent been covered above) - - // regexp - ["/foo(.*)/g;", "another regexp"], - // arrays - ["[];", "1 array"], - ["[ ];", "2 array"], - ["[1];", "3 array"], - ["[1,2];", "4 array"], - ["[1,2,,];", "5 array"], - ["[1,2,3];", "6 array"], - ["[1,2,3,,,];", "7 array"], - // objects - ["{};", "1 object"], - ["({x:5});", "2 object"], - ["({x:5,y:6});", "3 object"], - ["({x:5,});", "4 object"], - ["({if:5});", "5 object"], - ["({ get x() {42;} });", "6 object"], - ["({ set y(a) {1;} });", "7 object"], - // member expression - ["o.m;", "1 member expression"], - ["o['m'];", "2 member expression"], - ["o['n']['m'];", "3 member expression"], - ["o.n.m;", "4 member expression"], - ["o.if;", "5 member expression"], - // call and invoke expressions - ["f();", "1 call/invoke expression"], - ["f(x);", "2 call/invoke expression"], - ["f(x,y);", "3 call/invoke expression"], - ["o.m();", "4 call/invoke expression"], - ["o['m'];", "5 call/invoke expression"], - ["o.m(x);", "6 call/invoke expression"], - ["o['m'](x);", "7 call/invoke expression"], - ["o.m(x,y);", "8 call/invoke expression"], - ["o['m'](x,y);", "9 call/invoke expression"], - ["f(x)(y);", "10 call/invoke expression"], - ["f().x;", "11 call/invoke expression"], - - // eval - ["eval('x');", "1 eval"], - ["(eval)('x');", "2 eval"], - ["(1,eval)('x');", "3 eval"], - ["eval(x,y);", "4 eval"], - // new expression - ["new f();", "1 new expression"], - ["new o;", "2 new expression"], - ["new o.m;", "3 new expression"], - ["new o.m(x);", "4 new expression"], - ["new o.m(x,y);", "5 new expression"], - // prefix/postfix - ["++x;", "1 pre/postfix"], - ["x++;", "2 pre/postfix"], - ["--x;", "3 pre/postfix"], - ["x--;", "4 pre/postfix"], - ["x ++;", "5 pre/postfix"], - ["x /* comment */ ++;", "6 pre/postfix"], - ["++ /* comment */ x;", "7 pre/postfix"], - // unary operators - ["delete x;", "1 unary operator"], - ["void x;", "2 unary operator"], - ["+ x;", "3 unary operator"], - ["-x;", "4 unary operator"], - ["~x;", "5 unary operator"], - ["!x;", "6 unary operator"], - // meh - ["new Date++;", "new date ++"], - ["+x++;", " + x ++"], - // expression expressions - ["1 * 2;", "1 expression expressions"], - ["1 / 2;", "2 expression expressions"], - ["1 % 2;", "3 expression expressions"], - ["1 + 2;", "4 expression expressions"], - ["1 - 2;", "5 expression expressions"], - ["1 << 2;", "6 expression expressions"], - ["1 >>> 2;", "7 expression expressions"], - ["1 >> 2;", "8 expression expressions"], - ["1 * 2 + 3;", "9 expression expressions"], - ["(1+2)*3;", "10 expression expressions"], - ["1*(2+3);", "11 expression expressions"], - ["xy;", "13 expression expressions"], - ["x<=y;", "14 expression expressions"], - ["x>=y;", "15 expression expressions"], - ["x instanceof y;", "16 expression expressions"], - ["x in y;", "17 expression expressions"], - ["x&y;", "18 expression expressions"], - ["x^y;", "19 expression expressions"], - ["x|y;", "20 expression expressions"], - ["x+y>>= y;", "1 assignment"], - ["x <<= y;", "2 assignment"], - ["x = y;", "3 assignment"], - ["x += y;", "4 assignment"], - ["x /= y;", "5 assignment"], - // comma - ["x, y;", "comma"], - // block - ["{};", "1 block"], - ["{x;};", "2 block"], - ["{x;y;};", "3 block"], - // vars - ["var x;", "1 var"], - ["var x,y;", "2 var"], - ["var x=1,y=2;", "3 var"], - ["var x,y=2;", "4 var"], - // empty - [";", "1 empty"], - ["\n;", "2 empty"], - // expression statement - ["x;", "1 expression statement"], - ["5;", "2 expression statement"], - ["1+2;", "3 expression statement"], - // if - ["if (c) x; else y;", "1 if statement"], - ["if (c) x;", "2 if statement"], - ["if (c) {} else {};", "3 if statement"], - ["if (c1) if (c2) s1; else s2;", "4 if statement"], - // while - ["do s; while (e);", "1 while statement"], - ["do { s; } while (e);", "2 while statement"], - ["while (e) s;", "3 while statement"], - ["while (e) { s; };", "4 while statement"], - // for - ["for (;;) ;", "1 for statement"], - ["for (;c;x++) x;", "2 for statement"], - ["for (i;i> 1; -var c = 8 >>> 1; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js deleted file mode 100644 index 022f7a3..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue34.js +++ /dev/null @@ -1,3 +0,0 @@ -var a = {}; -a["this"] = 1; -a["that"] = 2; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js deleted file mode 100644 index 0b76103..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue4.js +++ /dev/null @@ -1,3 +0,0 @@ -var a = 2e3; -var b = 2e-3; -var c = 2e-5; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js deleted file mode 100644 index 031e85b..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue48.js +++ /dev/null @@ -1 +0,0 @@ -var s, i; s = ''; i = 0; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js deleted file mode 100644 index 060f9df..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue50.js +++ /dev/null @@ -1,9 +0,0 @@ -function bar(a) { - try { - foo(); - } catch(e) { - alert("Exception caught (foo not defined)"); - } - alert(a); // 10 in FF, "[object Error]" in IE -} -bar(10); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js deleted file mode 100644 index 4f8b32f..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue53.js +++ /dev/null @@ -1 +0,0 @@ -x = (y, z) diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js deleted file mode 100644 index 967052e..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue54.1.js +++ /dev/null @@ -1,3 +0,0 @@ -foo.toString(); -a.toString(16); -b.toString.call(c); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js deleted file mode 100644 index 14054d0..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue68.js +++ /dev/null @@ -1,5 +0,0 @@ -function f() { - if (a) return; - g(); - function g(){} -}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js deleted file mode 100644 index d25ecd6..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue69.js +++ /dev/null @@ -1 +0,0 @@ -[(a,b)] diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js deleted file mode 100644 index 6158861..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/issue9.js +++ /dev/null @@ -1,4 +0,0 @@ -var a = { - a: 1, - b: 2, // <-- trailing comma -}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js deleted file mode 100644 index c271a26..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/mangle.js +++ /dev/null @@ -1,5 +0,0 @@ -(function() { - var x = function fun(a, fun, b) { - return fun; - }; -}()); diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js deleted file mode 100644 index a675b1c..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/null_string.js +++ /dev/null @@ -1 +0,0 @@ -var nullString = "\0" \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js deleted file mode 100644 index b631f4c..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/strict-equals.js +++ /dev/null @@ -1,3 +0,0 @@ -typeof a === 'string' -b + "" !== c + "" -d < e === f < g diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js deleted file mode 100644 index 746ea98..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/var.js +++ /dev/null @@ -1,3 +0,0 @@ -// var declarations after each other should be combined -var a = 1; -var b = 2; \ No newline at end of file diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js deleted file mode 100644 index 6a15c46..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/whitespace.js +++ /dev/null @@ -1,21 +0,0 @@ -function id(a) { - // Form-Feed - // Vertical Tab - // No-Break Space - ᠎// Mongolian Vowel Separator -  // En quad -  // Em quad -  // En space -  // Em space -  // Three-Per-Em Space -  // Four-Per-Em Space -  // Six-Per-Em Space -  // Figure Space -  // Punctuation Space -  // Thin Space -  // Hair Space -  // Narrow No-Break Space -  // Medium Mathematical Space -  // Ideographic Space - return a; -} diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js deleted file mode 100644 index de266ed..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/compress/test/with.js +++ /dev/null @@ -1,2 +0,0 @@ -with({}) { -}; diff --git a/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js b/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js deleted file mode 100644 index 564abd3..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/test/unit/scripts.js +++ /dev/null @@ -1,57 +0,0 @@ -global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; - -var fs = require('fs'), - uglify = require('../../uglify-js'), - jsp = uglify.parser, - nodeunit = require('nodeunit'), - path = require('path'), - pro = uglify.uglify; - -var Script = process.binding('evals').Script; - -var scriptsPath = __dirname; - -function compress(code) { - var ast = jsp.parse(code); - ast = pro.ast_mangle(ast, { mangle: true }); - ast = pro.ast_squeeze(ast, { no_warnings: true }); - ast = pro.ast_squeeze_more(ast); - return pro.gen_code(ast); -}; - -var testDir = path.join(scriptsPath, "compress", "test"); -var expectedDir = path.join(scriptsPath, "compress", "expected"); - -function getTester(script) { - return function(test) { - var testPath = path.join(testDir, script); - var expectedPath = path.join(expectedDir, script); - var content = fs.readFileSync(testPath, 'utf-8'); - var outputCompress = compress(content); - - // Check if the noncompressdata is larger or same size as the compressed data - test.ok(content.length >= outputCompress.length); - - // Check that a recompress gives the same result - var outputReCompress = compress(content); - test.equal(outputCompress, outputReCompress); - - // Check if the compressed output is what is expected - var expected = fs.readFileSync(expectedPath, 'utf-8'); - test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); - - test.done(); - }; -}; - -var tests = {}; - -var scripts = fs.readdirSync(testDir); -for (var i in scripts) { - var script = scripts[i]; - if (/\.js$/.test(script)) { - tests[script] = getTester(script); - } -} - -module.exports = nodeunit.testCase(tests); diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js deleted file mode 100644 index 4bf2b94..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/tmp/hoist.js +++ /dev/null @@ -1,33 +0,0 @@ -function foo(arg1, arg2, arg3, arg4, arg5, arg6) { - var a = 5; - { - var d = 10, mak = 20, buz = 30; - var q = buz * 2; - } - if (moo) { - var a, b, c; - } - for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) - console.log(arg3); - for (var i in mak) {} - for (j in d) {} - var d; - - function test() { - - }; - - //test(); - - (function moo(first, second){ - console.log(first); - })(1); - - (function moo(first, second){ - console.log(moo()); - })(1); -} - - -var foo; -var bar; diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js deleted file mode 100644 index c6a9d79..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/tmp/instrument.js +++ /dev/null @@ -1,97 +0,0 @@ -// sample on how to use the parser and walker API to instrument some code - -var jsp = require("uglify-js").parser; -var pro = require("uglify-js").uglify; - -function instrument(code) { - var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want - // to have start/end tokens embedded in the - // statements - var w = pro.ast_walker(); - - // we're gonna need this to push elements that we're currently looking at, to avoid - // endless recursion. - var analyzing = []; - function do_stat() { - var ret; - if (this[0].start && analyzing.indexOf(this) < 0) { - // without the `analyzing' hack, w.walk(this) would re-enter here leading - // to infinite recursion - analyzing.push(this); - ret = [ "splice", // XXX: "block" is safer - [ [ "stat", - [ "call", [ "name", "trace" ], - [ [ "string", this[0].toString() ], - [ "num", this[0].start.line ], - [ "num", this[0].start.col ], - [ "num", this[0].end.line ], - [ "num", this[0].end.col ]]]], - w.walk(this) ]]; - analyzing.pop(this); - } - return ret; - }; - var new_ast = w.with_walkers({ - "stat" : do_stat, - "label" : do_stat, - "break" : do_stat, - "continue" : do_stat, - "debugger" : do_stat, - "var" : do_stat, - "const" : do_stat, - "return" : do_stat, - "throw" : do_stat, - "try" : do_stat, - "defun" : do_stat, - "if" : do_stat, - "while" : do_stat, - "do" : do_stat, - "for" : do_stat, - "for-in" : do_stat, - "switch" : do_stat, - "with" : do_stat - }, function(){ - return w.walk(ast); - }); - return pro.gen_code(new_ast, { beautify: true }); -} - - - - -////// test code follows. - -var code = instrument(test.toString()); -console.log(code); - -function test() { - // simple stats - a = 5; - c += a + b; - "foo"; - - // var - var foo = 5; - const bar = 6, baz = 7; - - // switch block. note we can't track case lines the same way. - switch ("foo") { - case "foo": - return 1; - case "bar": - return 2; - } - - // for/for in - for (var i = 0; i < 5; ++i) { - console.log("Hello " + i); - } - for (var i in [ 1, 2, 3]) { - console.log(i); - } - - // note however that the following is broken. I guess we - // should add the block brackets in this case... - for (var i = 0; i < 5; ++i) - console.log("foo"); -} diff --git a/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js b/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js deleted file mode 100644 index f295fba..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/tmp/test.js +++ /dev/null @@ -1,30 +0,0 @@ -#! /usr/bin/env node - -global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); -var fs = require("fs"); -var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js - jsp = uglify.parser, - pro = uglify.uglify; - -var code = fs.readFileSync("hoist.js", "utf8"); -var ast = jsp.parse(code); - -ast = pro.ast_lift_variables(ast); - -var w = pro.ast_walker(); -ast = w.with_walkers({ - "function": function() { - var node = w.dive(this); // walk depth first - console.log(pro.gen_code(node, { beautify: true })); - return node; - }, - "name": function(name) { - return [ this[0], "X" ]; - } -}, function(){ - return w.walk(ast); -}); - -console.log(pro.gen_code(ast, { - beautify: true -})); diff --git a/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js b/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js deleted file mode 100644 index 6e14a63..0000000 --- a/enyo/tools/minifier/node_modules/uglify-js/uglify-js.js +++ /dev/null @@ -1,18 +0,0 @@ -//convienence function(src, [options]); -function uglify(orig_code, options){ - options || (options = {}); - var jsp = uglify.parser; - var pro = uglify.uglify; - - var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST - ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names - ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations - var final_code = pro.gen_code(ast, options.gen_options); // compressed code here - return final_code; -}; - -uglify.parser = require("./lib/parse-js"); -uglify.uglify = require("./lib/process"); -uglify.consolidator = require("./lib/consolidator"); - -module.exports = uglify diff --git a/enyo/tools/minifier/node_modules/walker.js b/enyo/tools/minifier/node_modules/walker.js deleted file mode 100644 index 11c4355..0000000 --- a/enyo/tools/minifier/node_modules/walker.js +++ /dev/null @@ -1,40 +0,0 @@ -var fs = require("fs"); - -// -// setup DOM-like sandbox -// - -var window = {}; -var loader; - -var script = function(inPath) { - eval(fs.readFileSync(inPath, "utf8")); -}; - -module.exports = { - init: function(inEnyoPath) { - script(inEnyoPath + "/loader.js"); - enyo.path.addPaths({ - enyo: inEnyoPath, - lib: inEnyoPath + "/../lib" - }); - loader = new enyo.loaderFactory({ - script: function() {}, - sheet: function() {} - }); - loader.loadPackage = function(inScript) { - script(inScript); - }; - enyo.depends = function() { - //console.log(arguments); - loader.load.apply(loader, arguments); - }; - }, - walk: function(inScript, inCallback) { - //console.log("walking: ", inScript); - loader.finish = function() { - inCallback(loader); - }; - script(enyo.path.rewrite(inScript)); - } -} \ No newline at end of file diff --git a/enyo/tools/minifier/path-relative-shim.js b/enyo/tools/minifier/path-relative-shim.js deleted file mode 100644 index ea5d9b2..0000000 --- a/enyo/tools/minifier/path-relative-shim.js +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -/* - - path.relative shim for older versions of node - -*/ - -var isWindows = process.platform === 'win32'; -var path = require('path'); - -if (isWindows) { - - // path.relative(from, to) - // it will solve the relative path from 'from' to 'to', for instance: - // from = 'C:\\orandea\\test\\aaa' - // to = 'C:\\orandea\\impl\\bbb' - // The output of the function should be: '..\\..\\impl\\bbb' - // windows version - exports.relative = function(from, to) { - from = path.resolve(from); - to = path.resolve(to); - - // windows is not case sensitive - var lowerFrom = from.toLowerCase(); - var lowerTo = to.toLowerCase(); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var toParts = trim(to.split('\\')); - - var lowerFromParts = trim(lowerFrom.split('\\')); - var lowerToParts = trim(lowerTo.split('\\')); - - var length = Math.min(lowerFromParts.length, lowerToParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (lowerFromParts[i] !== lowerToParts[i]) { - samePartsLength = i; - break; - } - } - - if (samePartsLength == 0) { - return to; - } - - var outputParts = []; - for (var i = samePartsLength; i < lowerFromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('\\'); - }; - -} else /* posix */ { - - // path.relative(from, to) - // posix version - exports.relative = function(from, to) { - from = path.resolve(from).substr(1); - to = path.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - }; - -} \ No newline at end of file diff --git a/enyo/tools/minify.bat b/enyo/tools/minify.bat deleted file mode 100644 index a058a37..0000000 --- a/enyo/tools/minify.bat +++ /dev/null @@ -1,17 +0,0 @@ -REM don't watch the sausage being made -@ECHO OFF - -REM the folder this script is in (*/enyo/tools) -SET TOOLS=%~DP0 - -REM enyo location -SET ENYO=%TOOLS%\.. - -REM minify script location -SET MINIFY=%TOOLS%\minifier\minify.js - -REM node location -SET NODE=node.exe - -REM use node to invoke minify with a known path to enyo and imported parameters -%NODE% "%MINIFY%" -enyo "%ENYO%" %* diff --git a/enyo/tools/minify.sh b/enyo/tools/minify.sh deleted file mode 100644 index 80fedcc..0000000 --- a/enyo/tools/minify.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# the folder this script is in (*/enyo/tools) -TOOLS="$(cd `dirname $0`; pwd)" -# enyo location -ENYO="$TOOLS/.." -# minify script location -MINIFY="$TOOLS/minifier/minify.js" - -# check for node, but quietly -if command -v node >/dev/null 2>&1; then - # use node to invoke minify with a known path to enyo and imported parameters - echo "enyo/tools/minify.sh args: " $@ - node "$MINIFY" -enyo "$ENYO" $@ -else - echo "No node found in path" - exit 1 -fi diff --git a/enyo/tools/node_modules/.bin/nopt b/enyo/tools/node_modules/.bin/nopt deleted file mode 100644 index df90c72..0000000 --- a/enyo/tools/node_modules/.bin/nopt +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -var nopt = require("../lib/nopt") - , types = { num: Number - , bool: Boolean - , help: Boolean - , list: Array - , "num-list": [Number, Array] - , "str-list": [String, Array] - , "bool-list": [Boolean, Array] - , str: String } - , shorthands = { s: [ "--str", "astring" ] - , b: [ "--bool" ] - , nb: [ "--no-bool" ] - , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] - , "?": ["--help"] - , h: ["--help"] - , H: ["--help"] - , n: [ "--num", "125" ] } - , parsed = nopt( types - , shorthands - , process.argv - , 2 ) - -console.log("parsed", parsed) - -if (parsed.help) { - console.log("") - console.log("nopt cli tester") - console.log("") - console.log("types") - console.log(Object.keys(types).map(function M (t) { - var type = types[t] - if (Array.isArray(type)) { - return [t, type.map(function (type) { return type.name })] - } - return [t, type && type.name] - }).reduce(function (s, i) { - s[i[0]] = i[1] - return s - }, {})) - console.log("") - console.log("shorthands") - console.log(shorthands) -} diff --git a/enyo/tools/node_modules/.bin/shjs b/enyo/tools/node_modules/.bin/shjs deleted file mode 100644 index faa9995..0000000 --- a/enyo/tools/node_modules/.bin/shjs +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env node -require('../global'); - -if (process.argv.length < 3) { - console.log('ShellJS: missing argument (script name)'); - console.log(); - process.exit(1); -} - -var scriptName = process.argv[2]; -env['NODE_PATH'] = __dirname + '/../..'; - -if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { - if (test('-f', scriptName + '.js')) - scriptName += '.js'; - if (test('-f', scriptName + '.coffee')) - scriptName += '.coffee'; -} - -if (!test('-f', scriptName)) { - console.log('ShellJS: script not found ('+scriptName+')'); - console.log(); - process.exit(1); -} - - -if (scriptName.match(/\.coffee$/)) { - // - // CoffeeScript - // - if (which('coffee')) { - exec('coffee ' + scriptName, { async: true }); - } else { - console.log('ShellJS: CoffeeScript interpreter not found'); - console.log(); - process.exit(1); - } -} else { - // - // JavaScript - // - exec('node ' + scriptName, { async: true }); -} diff --git a/enyo/tools/node_modules/nopt/.npmignore b/enyo/tools/node_modules/nopt/.npmignore deleted file mode 100644 index e69de29..0000000 diff --git a/enyo/tools/node_modules/nopt/LICENSE b/enyo/tools/node_modules/nopt/LICENSE deleted file mode 100644 index 05a4010..0000000 --- a/enyo/tools/node_modules/nopt/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright 2009, 2010, 2011 Isaac Z. Schlueter. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/enyo/tools/node_modules/nopt/README.md b/enyo/tools/node_modules/nopt/README.md deleted file mode 100644 index f290da8..0000000 --- a/enyo/tools/node_modules/nopt/README.md +++ /dev/null @@ -1,210 +0,0 @@ -If you want to write an option parser, and have it be good, there are -two ways to do it. The Right Way, and the Wrong Way. - -The Wrong Way is to sit down and write an option parser. We've all done -that. - -The Right Way is to write some complex configurable program with so many -options that you go half-insane just trying to manage them all, and put -it off with duct-tape solutions until you see exactly to the core of the -problem, and finally snap and write an awesome option parser. - -If you want to write an option parser, don't write an option parser. -Write a package manager, or a source control system, or a service -restarter, or an operating system. You probably won't end up with a -good one of those, but if you don't give up, and you are relentless and -diligent enough in your procrastination, you may just end up with a very -nice option parser. - -## USAGE - - // my-program.js - var nopt = require("nopt") - , Stream = require("stream").Stream - , path = require("path") - , knownOpts = { "foo" : [String, null] - , "bar" : [Stream, Number] - , "baz" : path - , "bloo" : [ "big", "medium", "small" ] - , "flag" : Boolean - , "pick" : Boolean - , "many" : [String, Array] - } - , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] - , "b7" : ["--bar", "7"] - , "m" : ["--bloo", "medium"] - , "p" : ["--pick"] - , "f" : ["--flag"] - } - // everything is optional. - // knownOpts and shorthands default to {} - // arg list defaults to process.argv - // slice defaults to 2 - , parsed = nopt(knownOpts, shortHands, process.argv, 2) - console.log(parsed) - -This would give you support for any of the following: - -```bash -$ node my-program.js --foo "blerp" --no-flag -{ "foo" : "blerp", "flag" : false } - -$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag -{ bar: 7, foo: "Mr. Hand", flag: true } - -$ node my-program.js --foo "blerp" -f -----p -{ foo: "blerp", flag: true, pick: true } - -$ node my-program.js -fp --foofoo -{ foo: "Mr. Foo", flag: true, pick: true } - -$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. -{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } - -$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. -{ blatzk: 1000, flag: true, pick: true } - -$ node my-program.js --blatzk true -fp # but they need a value -{ blatzk: true, flag: true, pick: true } - -$ node my-program.js --no-blatzk -fp # unless they start with "no-" -{ blatzk: false, flag: true, pick: true } - -$ node my-program.js --baz b/a/z # known paths are resolved. -{ baz: "/Users/isaacs/b/a/z" } - -# if Array is one of the types, then it can take many -# values, and will always be an array. The other types provided -# specify what types are allowed in the list. - -$ node my-program.js --many 1 --many null --many foo -{ many: ["1", "null", "foo"] } - -$ node my-program.js --many foo -{ many: ["foo"] } -``` - -Read the tests at the bottom of `lib/nopt.js` for more examples of -what this puppy can do. - -## Types - -The following types are supported, and defined on `nopt.typeDefs` - -* String: A normal string. No parsing is done. -* path: A file system path. Gets resolved against cwd if not absolute. -* url: A url. If it doesn't parse, it isn't accepted. -* Number: Must be numeric. -* Date: Must parse as a date. If it does, and `Date` is one of the options, - then it will return a Date object, not a string. -* Boolean: Must be either `true` or `false`. If an option is a boolean, - then it does not need a value, and its presence will imply `true` as - the value. To negate boolean flags, do `--no-whatever` or `--whatever - false` -* NaN: Means that the option is strictly not allowed. Any value will - fail. -* Stream: An object matching the "Stream" class in node. Valuable - for use when validating programmatically. (npm uses this to let you - supply any WriteStream on the `outfd` and `logfd` config options.) -* Array: If `Array` is specified as one of the types, then the value - will be parsed as a list of options. This means that multiple values - can be specified, and that the value will always be an array. - -If a type is an array of values not on this list, then those are -considered valid values. For instance, in the example above, the -`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, -and any other value will be rejected. - -When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be -interpreted as their JavaScript equivalents, and numeric values will be -interpreted as a number. - -You can also mix types and values, or multiple types, in a list. For -instance `{ blah: [Number, null] }` would allow a value to be set to -either a Number or null. When types are ordered, this implies a -preference, and the first type that can be used to properly interpret -the value will be used. - -To define a new type, add it to `nopt.typeDefs`. Each item in that -hash is an object with a `type` member and a `validate` method. The -`type` member is an object that matches what goes in the type list. The -`validate` method is a function that gets called with `validate(data, -key, val)`. Validate methods should assign `data[key]` to the valid -value of `val` if it can be handled properly, or return boolean -`false` if it cannot. - -You can also call `nopt.clean(data, types, typeDefs)` to clean up a -config object and remove its invalid properties. - -## Error Handling - -By default, nopt outputs a warning to standard error when invalid -options are found. You can change this behavior by assigning a method -to `nopt.invalidHandler`. This method will be called with -the offending `nopt.invalidHandler(key, val, types)`. - -If no `nopt.invalidHandler` is assigned, then it will console.error -its whining. If it is assigned to boolean `false` then the warning is -suppressed. - -## Abbreviations - -Yes, they are supported. If you define options like this: - -```javascript -{ "foolhardyelephants" : Boolean -, "pileofmonkeys" : Boolean } -``` - -Then this will work: - -```bash -node program.js --foolhar --pil -node program.js --no-f --pileofmon -# etc. -``` - -## Shorthands - -Shorthands are a hash of shorter option names to a snippet of args that -they expand to. - -If multiple one-character shorthands are all combined, and the -combination does not unambiguously match any other option or shorthand, -then they will be broken up into their constituent parts. For example: - -```json -{ "s" : ["--loglevel", "silent"] -, "g" : "--global" -, "f" : "--force" -, "p" : "--parseable" -, "l" : "--long" -} -``` - -```bash -npm ls -sgflp -# just like doing this: -npm ls --loglevel silent --global --force --long --parseable -``` - -## The Rest of the args - -The config object returned by nopt is given a special member called -`argv`, which is an object with the following fields: - -* `remain`: The remaining args after all the parsing has occurred. -* `original`: The args as they originally appeared. -* `cooked`: The args after flags and shorthands are expanded. - -## Slicing - -Node programs are called with more or less the exact argv as it appears -in C land, after the v8 and node-specific options have been plucked off. -As such, `argv[0]` is always `node` and `argv[1]` is always the -JavaScript program being run. - -That's usually not very useful to you. So they're sliced off by -default. If you want them, then you can pass in `0` as the last -argument, or any other number that you'd like to slice off the start of -the list. diff --git a/enyo/tools/node_modules/nopt/bin/nopt.js b/enyo/tools/node_modules/nopt/bin/nopt.js deleted file mode 100644 index df90c72..0000000 --- a/enyo/tools/node_modules/nopt/bin/nopt.js +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -var nopt = require("../lib/nopt") - , types = { num: Number - , bool: Boolean - , help: Boolean - , list: Array - , "num-list": [Number, Array] - , "str-list": [String, Array] - , "bool-list": [Boolean, Array] - , str: String } - , shorthands = { s: [ "--str", "astring" ] - , b: [ "--bool" ] - , nb: [ "--no-bool" ] - , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] - , "?": ["--help"] - , h: ["--help"] - , H: ["--help"] - , n: [ "--num", "125" ] } - , parsed = nopt( types - , shorthands - , process.argv - , 2 ) - -console.log("parsed", parsed) - -if (parsed.help) { - console.log("") - console.log("nopt cli tester") - console.log("") - console.log("types") - console.log(Object.keys(types).map(function M (t) { - var type = types[t] - if (Array.isArray(type)) { - return [t, type.map(function (type) { return type.name })] - } - return [t, type && type.name] - }).reduce(function (s, i) { - s[i[0]] = i[1] - return s - }, {})) - console.log("") - console.log("shorthands") - console.log(shorthands) -} diff --git a/enyo/tools/node_modules/nopt/examples/my-program.js b/enyo/tools/node_modules/nopt/examples/my-program.js deleted file mode 100644 index 142447e..0000000 --- a/enyo/tools/node_modules/nopt/examples/my-program.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -//process.env.DEBUG_NOPT = 1 - -// my-program.js -var nopt = require("../lib/nopt") - , Stream = require("stream").Stream - , path = require("path") - , knownOpts = { "foo" : [String, null] - , "bar" : [Stream, Number] - , "baz" : path - , "bloo" : [ "big", "medium", "small" ] - , "flag" : Boolean - , "pick" : Boolean - } - , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] - , "b7" : ["--bar", "7"] - , "m" : ["--bloo", "medium"] - , "p" : ["--pick"] - , "f" : ["--flag", "true"] - , "g" : ["--flag"] - , "s" : "--flag" - } - // everything is optional. - // knownOpts and shorthands default to {} - // arg list defaults to process.argv - // slice defaults to 2 - , parsed = nopt(knownOpts, shortHands, process.argv, 2) - -console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/enyo/tools/node_modules/nopt/lib/nopt.js b/enyo/tools/node_modules/nopt/lib/nopt.js deleted file mode 100644 index 5763860..0000000 --- a/enyo/tools/node_modules/nopt/lib/nopt.js +++ /dev/null @@ -1,555 +0,0 @@ -// info about each config option. - -var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG - ? function () { console.error.apply(console, arguments) } - : function () {} - -var url = require("url") - , path = require("path") - , Stream = require("stream").Stream - , abbrev = require("abbrev") - -module.exports = exports = nopt -exports.clean = clean - -exports.typeDefs = - { String : { type: String, validate: validateString } - , Boolean : { type: Boolean, validate: validateBoolean } - , url : { type: url, validate: validateUrl } - , Number : { type: Number, validate: validateNumber } - , path : { type: path, validate: validatePath } - , Stream : { type: Stream, validate: validateStream } - , Date : { type: Date, validate: validateDate } - } - -function nopt (types, shorthands, args, slice) { - args = args || process.argv - types = types || {} - shorthands = shorthands || {} - if (typeof slice !== "number") slice = 2 - - debug(types, shorthands, args, slice) - - args = args.slice(slice) - var data = {} - , key - , remain = [] - , cooked = args - , original = args.slice(0) - - parse(args, data, remain, types, shorthands) - // now data is full - clean(data, types, exports.typeDefs) - data.argv = {remain:remain,cooked:cooked,original:original} - Object.defineProperty(data.argv, 'toString', { value: function () { - return this.original.map(JSON.stringify).join(" ") - }, enumerable: false }) - return data -} - -function clean (data, types, typeDefs) { - typeDefs = typeDefs || exports.typeDefs - var remove = {} - , typeDefault = [false, true, null, String, Number] - - Object.keys(data).forEach(function (k) { - if (k === "argv") return - var val = data[k] - , isArray = Array.isArray(val) - , type = types[k] - if (!isArray) val = [val] - if (!type) type = typeDefault - if (type === Array) type = typeDefault.concat(Array) - if (!Array.isArray(type)) type = [type] - - debug("val=%j", val) - debug("types=", type) - val = val.map(function (val) { - // if it's an unknown value, then parse false/true/null/numbers/dates - if (typeof val === "string") { - debug("string %j", val) - val = val.trim() - if ((val === "null" && ~type.indexOf(null)) - || (val === "true" && - (~type.indexOf(true) || ~type.indexOf(Boolean))) - || (val === "false" && - (~type.indexOf(false) || ~type.indexOf(Boolean)))) { - val = JSON.parse(val) - debug("jsonable %j", val) - } else if (~type.indexOf(Number) && !isNaN(val)) { - debug("convert to number", val) - val = +val - } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { - debug("convert to date", val) - val = new Date(val) - } - } - - if (!types.hasOwnProperty(k)) { - return val - } - - // allow `--no-blah` to set 'blah' to null if null is allowed - if (val === false && ~type.indexOf(null) && - !(~type.indexOf(false) || ~type.indexOf(Boolean))) { - val = null - } - - var d = {} - d[k] = val - debug("prevalidated val", d, val, types[k]) - if (!validate(d, k, val, types[k], typeDefs)) { - if (exports.invalidHandler) { - exports.invalidHandler(k, val, types[k], data) - } else if (exports.invalidHandler !== false) { - debug("invalid: "+k+"="+val, types[k]) - } - return remove - } - debug("validated val", d, val, types[k]) - return d[k] - }).filter(function (val) { return val !== remove }) - - if (!val.length) delete data[k] - else if (isArray) { - debug(isArray, data[k], val) - data[k] = val - } else data[k] = val[0] - - debug("k=%s val=%j", k, val, data[k]) - }) -} - -function validateString (data, k, val) { - data[k] = String(val) -} - -function validatePath (data, k, val) { - data[k] = path.resolve(String(val)) - return true -} - -function validateNumber (data, k, val) { - debug("validate Number %j %j %j", k, val, isNaN(val)) - if (isNaN(val)) return false - data[k] = +val -} - -function validateDate (data, k, val) { - debug("validate Date %j %j %j", k, val, Date.parse(val)) - var s = Date.parse(val) - if (isNaN(s)) return false - data[k] = new Date(val) -} - -function validateBoolean (data, k, val) { - if (val instanceof Boolean) val = val.valueOf() - else if (typeof val === "string") { - if (!isNaN(val)) val = !!(+val) - else if (val === "null" || val === "false") val = false - else val = true - } else val = !!val - data[k] = val -} - -function validateUrl (data, k, val) { - val = url.parse(String(val)) - if (!val.host) return false - data[k] = val.href -} - -function validateStream (data, k, val) { - if (!(val instanceof Stream)) return false - data[k] = val -} - -function validate (data, k, val, type, typeDefs) { - // arrays are lists of types. - if (Array.isArray(type)) { - for (var i = 0, l = type.length; i < l; i ++) { - if (type[i] === Array) continue - if (validate(data, k, val, type[i], typeDefs)) return true - } - delete data[k] - return false - } - - // an array of anything? - if (type === Array) return true - - // NaN is poisonous. Means that something is not allowed. - if (type !== type) { - debug("Poison NaN", k, val, type) - delete data[k] - return false - } - - // explicit list of values - if (val === type) { - debug("Explicitly allowed %j", val) - // if (isArray) (data[k] = data[k] || []).push(val) - // else data[k] = val - data[k] = val - return true - } - - // now go through the list of typeDefs, validate against each one. - var ok = false - , types = Object.keys(typeDefs) - for (var i = 0, l = types.length; i < l; i ++) { - debug("test type %j %j %j", k, val, types[i]) - var t = typeDefs[types[i]] - if (t && type === t.type) { - var d = {} - ok = false !== t.validate(d, k, val) - val = d[k] - if (ok) { - // if (isArray) (data[k] = data[k] || []).push(val) - // else data[k] = val - data[k] = val - break - } - } - } - debug("OK? %j (%j %j %j)", ok, k, val, types[i]) - - if (!ok) delete data[k] - return ok -} - -function parse (args, data, remain, types, shorthands) { - debug("parse", args, data, remain) - - var key = null - , abbrevs = abbrev(Object.keys(types)) - , shortAbbr = abbrev(Object.keys(shorthands)) - - for (var i = 0; i < args.length; i ++) { - var arg = args[i] - debug("arg", arg) - - if (arg.match(/^-{2,}$/)) { - // done with keys. - // the rest are args. - remain.push.apply(remain, args.slice(i + 1)) - args[i] = "--" - break - } - var hadEq = false - if (arg.charAt(0) === "-") { - if (arg.indexOf("=") !== -1) { - hadEq = true - var v = arg.split("=") - arg = v.shift() - v = v.join("=") - args.splice.apply(args, [i, 1].concat([arg, v])) - } - // see if it's a shorthand - // if so, splice and back up to re-parse it. - var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) - debug("arg=%j shRes=%j", arg, shRes) - if (shRes) { - debug(arg, shRes) - args.splice.apply(args, [i, 1].concat(shRes)) - if (arg !== shRes[0]) { - i -- - continue - } - } - arg = arg.replace(/^-+/, "") - var no = null - while (arg.toLowerCase().indexOf("no-") === 0) { - no = !no - arg = arg.substr(3) - } - - if (abbrevs[arg]) arg = abbrevs[arg] - - var isArray = types[arg] === Array || - Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 - - var val - , la = args[i + 1] - - var isBool = typeof no === 'boolean' || - types[arg] === Boolean || - Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || - (typeof types[arg] === 'undefined' && !hadEq) || - (la === "false" && - (types[arg] === null || - Array.isArray(types[arg]) && ~types[arg].indexOf(null))) - - if (isBool) { - // just set and move along - val = !no - // however, also support --bool true or --bool false - if (la === "true" || la === "false") { - val = JSON.parse(la) - la = null - if (no) val = !val - i ++ - } - - // also support "foo":[Boolean, "bar"] and "--foo bar" - if (Array.isArray(types[arg]) && la) { - if (~types[arg].indexOf(la)) { - // an explicit type - val = la - i ++ - } else if ( la === "null" && ~types[arg].indexOf(null) ) { - // null allowed - val = null - i ++ - } else if ( !la.match(/^-{2,}[^-]/) && - !isNaN(la) && - ~types[arg].indexOf(Number) ) { - // number - val = +la - i ++ - } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { - // string - val = la - i ++ - } - } - - if (isArray) (data[arg] = data[arg] || []).push(val) - else data[arg] = val - - continue - } - - if (la && la.match(/^-{2,}$/)) { - la = undefined - i -- - } - - val = la === undefined ? true : la - if (isArray) (data[arg] = data[arg] || []).push(val) - else data[arg] = val - - i ++ - continue - } - remain.push(arg) - } -} - -function resolveShort (arg, shorthands, shortAbbr, abbrevs) { - // handle single-char shorthands glommed together, like - // npm ls -glp, but only if there is one dash, and only if - // all of the chars are single-char shorthands, and it's - // not a match to some other abbrev. - arg = arg.replace(/^-+/, '') - if (abbrevs[arg] && !shorthands[arg]) { - return null - } - if (shortAbbr[arg]) { - arg = shortAbbr[arg] - } else { - var singles = shorthands.___singles - if (!singles) { - singles = Object.keys(shorthands).filter(function (s) { - return s.length === 1 - }).reduce(function (l,r) { l[r] = true ; return l }, {}) - shorthands.___singles = singles - } - var chrs = arg.split("").filter(function (c) { - return singles[c] - }) - if (chrs.join("") === arg) return chrs.map(function (c) { - return shorthands[c] - }).reduce(function (l, r) { - return l.concat(r) - }, []) - } - - if (shorthands[arg] && !Array.isArray(shorthands[arg])) { - shorthands[arg] = shorthands[arg].split(/\s+/) - } - return shorthands[arg] -} - -if (module === require.main) { -var assert = require("assert") - , util = require("util") - - , shorthands = - { s : ["--loglevel", "silent"] - , d : ["--loglevel", "info"] - , dd : ["--loglevel", "verbose"] - , ddd : ["--loglevel", "silly"] - , noreg : ["--no-registry"] - , reg : ["--registry"] - , "no-reg" : ["--no-registry"] - , silent : ["--loglevel", "silent"] - , verbose : ["--loglevel", "verbose"] - , h : ["--usage"] - , H : ["--usage"] - , "?" : ["--usage"] - , help : ["--usage"] - , v : ["--version"] - , f : ["--force"] - , desc : ["--description"] - , "no-desc" : ["--no-description"] - , "local" : ["--no-global"] - , l : ["--long"] - , p : ["--parseable"] - , porcelain : ["--parseable"] - , g : ["--global"] - } - - , types = - { aoa: Array - , nullstream: [null, Stream] - , date: Date - , str: String - , browser : String - , cache : path - , color : ["always", Boolean] - , depth : Number - , description : Boolean - , dev : Boolean - , editor : path - , force : Boolean - , global : Boolean - , globalconfig : path - , group : [String, Number] - , gzipbin : String - , logfd : [Number, Stream] - , loglevel : ["silent","win","error","warn","info","verbose","silly"] - , long : Boolean - , "node-version" : [false, String] - , npaturl : url - , npat : Boolean - , "onload-script" : [false, String] - , outfd : [Number, Stream] - , parseable : Boolean - , pre: Boolean - , prefix: path - , proxy : url - , "rebuild-bundle" : Boolean - , registry : url - , searchopts : String - , searchexclude: [null, String] - , shell : path - , t: [Array, String] - , tag : String - , tar : String - , tmp : path - , "unsafe-perm" : Boolean - , usage : Boolean - , user : String - , username : String - , userconfig : path - , version : Boolean - , viewer: path - , _exit : Boolean - } - -; [["-v", {version:true}, []] - ,["---v", {version:true}, []] - ,["ls -s --no-reg connect -d", - {loglevel:"info",registry:null},["ls","connect"]] - ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] - ,["ls --registry blargle", {}, ["ls"]] - ,["--no-registry", {registry:null}, []] - ,["--no-color true", {color:false}, []] - ,["--no-color false", {color:true}, []] - ,["--no-color", {color:false}, []] - ,["--color false", {color:false}, []] - ,["--color --logfd 7", {logfd:7,color:true}, []] - ,["--color=true", {color:true}, []] - ,["--logfd=10", {logfd:10}, []] - ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] - ,["--tmp=tmp -tar=gtar", - {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] - ,["--logfd x", {}, []] - ,["a -true -- -no-false", {true:true},["a","-no-false"]] - ,["a -no-false", {false:false},["a"]] - ,["a -no-no-true", {true:true}, ["a"]] - ,["a -no-no-no-false", {false:false}, ["a"]] - ,["---NO-no-No-no-no-no-nO-no-no"+ - "-No-no-no-no-no-no-no-no-no"+ - "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ - "-no-body-can-do-the-boogaloo-like-I-do" - ,{"body-can-do-the-boogaloo-like-I-do":false}, []] - ,["we are -no-strangers-to-love "+ - "--you-know=the-rules --and=so-do-i "+ - "---im-thinking-of=a-full-commitment "+ - "--no-you-would-get-this-from-any-other-guy "+ - "--no-gonna-give-you-up "+ - "-no-gonna-let-you-down=true "+ - "--no-no-gonna-run-around false "+ - "--desert-you=false "+ - "--make-you-cry false "+ - "--no-tell-a-lie "+ - "--no-no-and-hurt-you false" - ,{"strangers-to-love":false - ,"you-know":"the-rules" - ,"and":"so-do-i" - ,"you-would-get-this-from-any-other-guy":false - ,"gonna-give-you-up":false - ,"gonna-let-you-down":false - ,"gonna-run-around":false - ,"desert-you":false - ,"make-you-cry":false - ,"tell-a-lie":false - ,"and-hurt-you":false - },["we", "are"]] - ,["-t one -t two -t three" - ,{t: ["one", "two", "three"]} - ,[]] - ,["-t one -t null -t three four five null" - ,{t: ["one", "null", "three"]} - ,["four", "five", "null"]] - ,["-t foo" - ,{t:["foo"]} - ,[]] - ,["--no-t" - ,{t:["false"]} - ,[]] - ,["-no-no-t" - ,{t:["true"]} - ,[]] - ,["-aoa one -aoa null -aoa 100" - ,{aoa:["one", null, 100]} - ,[]] - ,["-str 100" - ,{str:"100"} - ,[]] - ,["--color always" - ,{color:"always"} - ,[]] - ,["--no-nullstream" - ,{nullstream:null} - ,[]] - ,["--nullstream false" - ,{nullstream:null} - ,[]] - ,["--notadate=2011-01-25" - ,{notadate: "2011-01-25"} - ,[]] - ,["--date 2011-01-25" - ,{date: new Date("2011-01-25")} - ,[]] - ].forEach(function (test) { - var argv = test[0].split(/\s+/) - , opts = test[1] - , rem = test[2] - , actual = nopt(types, shorthands, argv, 0) - , parsed = actual.argv - delete actual.argv - console.log(util.inspect(actual, false, 2, true), parsed.remain) - for (var i in opts) { - var e = JSON.stringify(opts[i]) - , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) - if (e && typeof e === "object") { - assert.deepEqual(e, a) - } else { - assert.equal(e, a) - } - } - assert.deepEqual(rem, parsed.remain) - }) -} diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md b/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md deleted file mode 100644 index 99746fe..0000000 --- a/enyo/tools/node_modules/nopt/node_modules/abbrev/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# abbrev-js - -Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). - -Usage: - - var abbrev = require("abbrev"); - abbrev("foo", "fool", "folding", "flop"); - - // returns: - { fl: 'flop' - , flo: 'flop' - , flop: 'flop' - , fol: 'folding' - , fold: 'folding' - , foldi: 'folding' - , foldin: 'folding' - , folding: 'folding' - , foo: 'foo' - , fool: 'fool' - } - -This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js deleted file mode 100644 index 037de2d..0000000 --- a/enyo/tools/node_modules/nopt/node_modules/abbrev/lib/abbrev.js +++ /dev/null @@ -1,106 +0,0 @@ - -module.exports = exports = abbrev.abbrev = abbrev - -abbrev.monkeyPatch = monkeyPatch - -function monkeyPatch () { - Array.prototype.abbrev = function () { return abbrev(this) } - Object.prototype.abbrev = function () { return abbrev(Object.keys(this)) } -} - -function abbrev (list) { - if (arguments.length !== 1 || !Array.isArray(list)) { - list = Array.prototype.slice.call(arguments, 0) - } - for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { - args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) - } - - // sort them lexicographically, so that they're next to their nearest kin - args = args.sort(lexSort) - - // walk through each, seeing how much it has in common with the next and previous - var abbrevs = {} - , prev = "" - for (var i = 0, l = args.length ; i < l ; i ++) { - var current = args[i] - , next = args[i + 1] || "" - , nextMatches = true - , prevMatches = true - if (current === next) continue - for (var j = 0, cl = current.length ; j < cl ; j ++) { - var curChar = current.charAt(j) - nextMatches = nextMatches && curChar === next.charAt(j) - prevMatches = prevMatches && curChar === prev.charAt(j) - if (nextMatches || prevMatches) continue - else { - j ++ - break - } - } - prev = current - if (j === cl) { - abbrevs[current] = current - continue - } - for (var a = current.substr(0, j) ; j <= cl ; j ++) { - abbrevs[a] = current - a += current.charAt(j) - } - } - return abbrevs -} - -function lexSort (a, b) { - return a === b ? 0 : a > b ? 1 : -1 -} - - -// tests -if (module === require.main) { - -var assert = require("assert") - , sys -sys = require("util") - -console.log("running tests") -function test (list, expect) { - var actual = abbrev(list) - assert.deepEqual(actual, expect, - "abbrev("+sys.inspect(list)+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) - actual = abbrev.apply(exports, list) - assert.deepEqual(abbrev.apply(exports, list), expect, - "abbrev("+list.map(JSON.stringify).join(",")+") === " + sys.inspect(expect) + "\n"+ - "actual: "+sys.inspect(actual)) -} - -test([ "ruby", "ruby", "rules", "rules", "rules" ], -{ rub: 'ruby' -, ruby: 'ruby' -, rul: 'rules' -, rule: 'rules' -, rules: 'rules' -}) -test(["fool", "foom", "pool", "pope"], -{ fool: 'fool' -, foom: 'foom' -, poo: 'pool' -, pool: 'pool' -, pop: 'pope' -, pope: 'pope' -}) -test(["a", "ab", "abc", "abcd", "abcde", "acde"], -{ a: 'a' -, ab: 'ab' -, abc: 'abc' -, abcd: 'abcd' -, abcde: 'abcde' -, ac: 'acde' -, acd: 'acde' -, acde: 'acde' -}) - -console.log("pass") - -} diff --git a/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json b/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json deleted file mode 100644 index 09b485e..0000000 --- a/enyo/tools/node_modules/nopt/node_modules/abbrev/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "abbrev", - "version": "1.0.3", - "description": "Like ruby's abbrev module, but in js", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me" - }, - "main": "./lib/abbrev.js", - "scripts": { - "test": "node lib/abbrev.js" - }, - "repository": { - "type": "git", - "url": "http://github.com/isaacs/abbrev-js" - }, - "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", - "_id": "abbrev@1.0.3", - "_from": "abbrev@1" -} diff --git a/enyo/tools/node_modules/nopt/package.json b/enyo/tools/node_modules/nopt/package.json deleted file mode 100644 index 77a120d..0000000 --- a/enyo/tools/node_modules/nopt/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "nopt", - "version": "2.0.0", - "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "main": "lib/nopt.js", - "scripts": { - "test": "node lib/nopt.js" - }, - "repository": { - "type": "git", - "url": "http://github.com/isaacs/nopt" - }, - "bin": { - "nopt": "./bin/nopt.js" - }, - "license": { - "type": "MIT", - "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" - }, - "dependencies": { - "abbrev": "1" - }, - "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", - "_id": "nopt@2.0.0", - "_from": "nopt" -} diff --git a/enyo/tools/node_modules/shelljs/.documentup.json b/enyo/tools/node_modules/shelljs/.documentup.json deleted file mode 100644 index 2d0c727..0000000 --- a/enyo/tools/node_modules/shelljs/.documentup.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "ShellJS", - "twitter": [ - "arturadib" - ] -} diff --git a/enyo/tools/node_modules/shelljs/.travis.yml b/enyo/tools/node_modules/shelljs/.travis.yml deleted file mode 100644 index 70076dc..0000000 --- a/enyo/tools/node_modules/shelljs/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js -node_js: - - 0.4 - - 0.6 - - 0.7 # development version of 0.8, may be unstable - diff --git a/enyo/tools/node_modules/shelljs/LICENSE b/enyo/tools/node_modules/shelljs/LICENSE deleted file mode 100644 index 1b35ee9..0000000 --- a/enyo/tools/node_modules/shelljs/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2012, Artur Adib -All rights reserved. - -You may use this project under the terms of the New BSD license as follows: - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Artur Adib nor the - names of the contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/enyo/tools/node_modules/shelljs/README.md b/enyo/tools/node_modules/shelljs/README.md deleted file mode 100644 index ddf5f5d..0000000 --- a/enyo/tools/node_modules/shelljs/README.md +++ /dev/null @@ -1,421 +0,0 @@ -# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs) - -ShellJS is a portable (**Windows included**) implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts! - -The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and is being used at Mozilla's [PDF.js](http://github.com/mozilla/pdf.js), [Butter.js](http://github.com/mozilla/butter) and [others](http://search.npmjs.org/#/shelljs). - - -## Installing - -Via npm: - -```bash -$ npm install [-g] shelljs -``` - -If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to -run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder: - -```bash -$ shjs my_script -``` - -You can also just copy `shell.js` into your project's directory, and `require()` accordingly. - - -## Examples - -### JavaScript - -```javascript -require('shelljs/global'); - -if (!which('git')) { - echo('Sorry, this script requires git'); - exit(1); -} - -// Copy files to release dir -mkdir('-p', 'out/Release'); -cp('-R', 'stuff/*', 'out/Release'); - -// Replace macros in each .js file -cd('lib'); -ls('*.js').forEach(function(file) { - sed('-i', 'BUILD_VERSION', 'v0.1.2', file); - sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file); - sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file); -}); -cd('..'); - -// Run external tool synchronously -if (exec('git commit -am "Auto-commit"').code !== 0) { - echo('Error: Git commit failed'); - exit(1); -} -``` - -### CoffeeScript - -```coffeescript -require 'shelljs/global' - -if not which 'git' - echo 'Sorry, this script requires git' - exit 1 - -# Copy files to release dir -mkdir '-p', 'out/Release' -cp '-R', 'stuff/*', 'out/Release' - -# Replace macros in each .js file -cd 'lib' -for file in ls '*.js' - sed '-i', 'BUILD_VERSION', 'v0.1.2', file - sed '-i', /.*REMOVE_THIS_LINE.*\n/, '', file - sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat 'macro.js', file -cd '..' - -# Run external tool synchronously -if (exec 'git commit -am "Auto-commit"').code != 0 - echo 'Error: Git commit failed' - exit 1 -``` - -## Global vs. Local - -The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`. - -Example: - -```javascript -var shell = require('shelljs'); -shell.echo('hello world'); -``` - -## Make tool - -A convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script. - -Example (CoffeeScript): - -```coffeescript -require 'shelljs/make' - -target.all = -> - target.bundle() - target.docs() - -target.bundle = -> - cd __dirname - mkdir 'build' - cd 'lib' - (cat '*.js').to '../build/output.js' - -target.docs = -> - cd __dirname - mkdir 'docs' - cd 'lib' - for file in ls '*.js' - text = grep '//@', file # extract special comments - text.replace '//@', '' # remove comment tags - text.to 'docs/my_docs.md' -``` - -To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on. - - - - - - -## Command reference - - -All commands run synchronously, unless otherwise stated. - - -### cd('dir') -Changes to directory `dir` for the duration of the script - -### pwd() -Returns the current directory. - -### ls([options ,] path [,path ...]) -### ls([options ,] path_array) -Available options: - -+ `-R`: recursive -+ `-A`: all files (include files beginning with `.`, except for `.` and `..`) - -Examples: - -```javascript -ls('projs/*.js'); -ls('-R', '/users/me', '/tmp'); -ls('-R', ['/users/me', '/tmp']); // same as above -``` - -Returns array of files in the given path, or in current directory if no path provided. - -### find(path [,path ...]) -### find(path_array) -Examples: - -```javascript -find('src', 'lib'); -find(['src', 'lib']); // same as above -find('.').filter(function(file) { return file.match(/\.js$/); }); -``` - -Returns array of all files (however deep) in the given paths. - -The main difference from `ls('-R', path)` is that the resulting file names -include the base directories, e.g. `lib/resources/file1` instead of just `file1`. - -### cp([options ,] source [,source ...], dest) -### cp([options ,] source_array, dest) -Available options: - -+ `-f`: force -+ `-r, -R`: recursive - -Examples: - -```javascript -cp('file1', 'dir1'); -cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); -cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above -``` - -Copies files. The wildcard `*` is accepted. - -### rm([options ,] file [, file ...]) -### rm([options ,] file_array) -Available options: - -+ `-f`: force -+ `-r, -R`: recursive - -Examples: - -```javascript -rm('-rf', '/tmp/*'); -rm('some_file.txt', 'another_file.txt'); -rm(['some_file.txt', 'another_file.txt']); // same as above -``` - -Removes files. The wildcard `*` is accepted. - -### mv(source [, source ...], dest') -### mv(source_array, dest') -Available options: - -+ `f`: force - -Examples: - -```javascript -mv('-f', 'file', 'dir/'); -mv('file1', 'file2', 'dir/'); -mv(['file1', 'file2'], 'dir/'); // same as above -``` - -Moves files. The wildcard `*` is accepted. - -### mkdir([options ,] dir [, dir ...]) -### mkdir([options ,] dir_array) -Available options: - -+ `p`: full path (will create intermediate dirs if necessary) - -Examples: - -```javascript -mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); -mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above -``` - -Creates directories. - -### test(expression) -Available expression primaries: - -+ `'-b', 'path'`: true if path is a block device -+ `'-c', 'path'`: true if path is a character device -+ `'-d', 'path'`: true if path is a directory -+ `'-e', 'path'`: true if path exists -+ `'-f', 'path'`: true if path is a regular file -+ `'-L', 'path'`: true if path is a symboilc link -+ `'-p', 'path'`: true if path is a pipe (FIFO) -+ `'-S', 'path'`: true if path is a socket - -Examples: - -```javascript -if (test('-d', path)) { /* do something with dir */ }; -if (!test('-f', path)) continue; // skip if it's a regular file -``` - -Evaluates expression using the available primaries and returns corresponding value. - -### cat(file [, file ...]) -### cat(file_array) - -Examples: - -```javascript -var str = cat('file*.txt'); -var str = cat('file1', 'file2'); -var str = cat(['file1', 'file2']); // same as above -``` - -Returns a string containing the given file, or a concatenated string -containing the files if more than one file is given (a new line character is -introduced between each file). Wildcard `*` accepted. - -### 'string'.to(file) - -Examples: - -```javascript -cat('input.txt').to('output.txt'); -``` - -Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as -those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ - -### sed([options ,] search_regex, replace_str, file) -Available options: - -+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ - -Examples: - -```javascript -sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); -sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); -``` - -Reads an input string from `file` and performs a JavaScript `replace()` on the input -using the given search regex and replacement string. Returns the new string after replacement. - -### grep([options ,] regex_filter, file [, file ...]) -### grep([options ,] regex_filter, file_array) -Available options: - -+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria. - -Examples: - -```javascript -grep('-v', 'GLOBAL_VARIABLE', '*.js'); -grep('GLOBAL_VARIABLE', '*.js'); -``` - -Reads input string from given files and returns a string containing all lines of the -file that match the given `regex_filter`. Wildcard `*` accepted. - -### which(command) - -Examples: - -```javascript -var nodeExec = which('node'); -``` - -Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. -Returns string containing the absolute path to the command. - -### echo(string [,string ...]) - -Examples: - -```javascript -echo('hello world'); -var str = echo('hello world'); -``` - -Prints string to stdout, and returns string with additional utility methods -like `.to()`. - -### exit(code) -Exits the current process with the given exit code. - -### env['VAR_NAME'] -Object containing environment variables (both getter and setter). Shortcut to process.env. - -### exec(command [, options] [, callback]) -Available options (all `false` by default): - -+ `async`: Asynchronous execution. Defaults to true if a callback is provided. -+ `silent`: Do not echo program output to console. - -Examples: - -```javascript -var version = exec('node --version', {silent:true}).output; - -var child = exec('some_long_running_process', {async:true}); -child.stdout.on('data', function(data) { - /* ... do something with data ... */ -}); - -exec('some_long_running_process', function(code, output) { - console.log('Exit code:', code); - console.log('Program output:', output); -}); -``` - -Executes the given `command` _synchronously_, unless otherwise specified. -When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's -`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and -the `callback` gets the arguments `(code, output)`. - -**Note:** For long-lived processes, it's best to run `exec()` asynchronously as -the current synchronous implementation uses a lot of CPU. This should be getting -fixed soon. - -## Non-Unix commands - - -### tempdir() -Searches and returns string containing a writeable, platform-dependent temporary directory. -Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). - -### error() -Tests if error occurred in the last command. Returns `null` if no error occurred, -otherwise returns string explaining the error - -### silent([state]) -Example: - -```javascript -var silentState = silent(); -silent(true); -/* ... */ -silent(silentState); // restore old silent state -``` - -Suppresses all command output if `state = true`, except for `echo()` calls. -Returns state if no arguments given. - -## Deprecated - - -### exists(path [, path ...]) -### exists(path_array) - -_This function is being deprecated. Use `test()` instead._ - -Returns true if all the given paths exist. - -### verbose() - -_This function is being deprecated. Use `silent(false) instead.`_ - -Enables all output (default) diff --git a/enyo/tools/node_modules/shelljs/bin/shjs b/enyo/tools/node_modules/shelljs/bin/shjs deleted file mode 100644 index faa9995..0000000 --- a/enyo/tools/node_modules/shelljs/bin/shjs +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env node -require('../global'); - -if (process.argv.length < 3) { - console.log('ShellJS: missing argument (script name)'); - console.log(); - process.exit(1); -} - -var scriptName = process.argv[2]; -env['NODE_PATH'] = __dirname + '/../..'; - -if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { - if (test('-f', scriptName + '.js')) - scriptName += '.js'; - if (test('-f', scriptName + '.coffee')) - scriptName += '.coffee'; -} - -if (!test('-f', scriptName)) { - console.log('ShellJS: script not found ('+scriptName+')'); - console.log(); - process.exit(1); -} - - -if (scriptName.match(/\.coffee$/)) { - // - // CoffeeScript - // - if (which('coffee')) { - exec('coffee ' + scriptName, { async: true }); - } else { - console.log('ShellJS: CoffeeScript interpreter not found'); - console.log(); - process.exit(1); - } -} else { - // - // JavaScript - // - exec('node ' + scriptName, { async: true }); -} diff --git a/enyo/tools/node_modules/shelljs/global.js b/enyo/tools/node_modules/shelljs/global.js deleted file mode 100644 index 83a27e6..0000000 --- a/enyo/tools/node_modules/shelljs/global.js +++ /dev/null @@ -1,3 +0,0 @@ -var shell = require('./shell.js'); -for (cmd in shell) - global[cmd] = shell[cmd]; diff --git a/enyo/tools/node_modules/shelljs/make.js b/enyo/tools/node_modules/shelljs/make.js deleted file mode 100644 index c495735..0000000 --- a/enyo/tools/node_modules/shelljs/make.js +++ /dev/null @@ -1,46 +0,0 @@ -require('./global'); - -global.target = {}; - -// This ensures we only execute the script targets after the entire script has -// been evaluated -var args = process.argv.slice(2); -setTimeout(function() { - - if (args.length === 1 && args[0] === '--help') { - console.log('Available targets:'); - for (t in target) - console.log(' ' + t); - return; - } - - // Wrap targets to prevent duplicate execution - for (t in target) { - (function(t, oldTarget){ - - // Wrap it - target[t] = function(force) { - if (oldTarget.done && !force) - return; - oldTarget.done = true; - return oldTarget.apply(oldTarget, arguments); - } - - })(t, target[t]); - } - - // Execute desired targets - if (args.length > 0) { - args.forEach(function(arg) { - if (arg in target) - target[arg](); - else { - console.log('no such target: ' + arg); - exit(1); - } - }); - } else if ('all' in target) { - target.all(); - } - -}, 0); diff --git a/enyo/tools/node_modules/shelljs/package.json b/enyo/tools/node_modules/shelljs/package.json deleted file mode 100644 index a3cfd41..0000000 --- a/enyo/tools/node_modules/shelljs/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "shelljs", - "version": "0.0.8", - "author": { - "name": "Artur Adib", - "email": "aadib@mozilla.com" - }, - "description": "Portable Unix shell commands for Node.js", - "keywords": [ - "unix", - "shell", - "makefile", - "make", - "jake", - "synchronous" - ], - "repository": { - "type": "git", - "url": "git://github.com/arturadib/shelljs.git" - }, - "homepage": "http://github.com/arturadib/shelljs", - "main": "./shell.js", - "scripts": { - "test": "node scripts/run-tests" - }, - "bin": { - "shjs": "./bin/shjs" - }, - "dependencies": {}, - "devDependencies": {}, - "optionalDependencies": {}, - "engines": { - "node": "*" - }, - "readme": "# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs)\n\nShellJS is a portable (**Windows included**) implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts!\n\nThe project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and is being used at Mozilla's [PDF.js](http://github.com/mozilla/pdf.js), [Butter.js](http://github.com/mozilla/butter) and [others](http://search.npmjs.org/#/shelljs).\n\n\n## Installing\n\nVia npm:\n\n```bash\n$ npm install [-g] shelljs\n```\n\nIf the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to\nrun ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:\n\n```bash\n$ shjs my_script\n```\n\nYou can also just copy `shell.js` into your project's directory, and `require()` accordingly.\n\n\n## Examples\n\n### JavaScript\n\n```javascript\nrequire('shelljs/global');\n\nif (!which('git')) {\n echo('Sorry, this script requires git');\n exit(1);\n}\n\n// Copy files to release dir\nmkdir('-p', 'out/Release');\ncp('-R', 'stuff/*', 'out/Release');\n\n// Replace macros in each .js file\ncd('lib');\nls('*.js').forEach(function(file) {\n sed('-i', 'BUILD_VERSION', 'v0.1.2', file);\n sed('-i', /.*REMOVE_THIS_LINE.*\\n/, '', file);\n sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat('macro.js'), file);\n});\ncd('..');\n\n// Run external tool synchronously\nif (exec('git commit -am \"Auto-commit\"').code !== 0) {\n echo('Error: Git commit failed');\n exit(1);\n}\n```\n\n### CoffeeScript\n\n```coffeescript\nrequire 'shelljs/global'\n\nif not which 'git'\n echo 'Sorry, this script requires git'\n exit 1\n\n# Copy files to release dir\nmkdir '-p', 'out/Release'\ncp '-R', 'stuff/*', 'out/Release'\n\n# Replace macros in each .js file\ncd 'lib'\nfor file in ls '*.js'\n sed '-i', 'BUILD_VERSION', 'v0.1.2', file\n sed '-i', /.*REMOVE_THIS_LINE.*\\n/, '', file\n sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat 'macro.js', file\ncd '..'\n\n# Run external tool synchronously\nif (exec 'git commit -am \"Auto-commit\"').code != 0\n echo 'Error: Git commit failed'\n exit 1\n```\n\n## Global vs. Local\n\nThe example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.\n\nExample:\n\n```javascript\nvar shell = require('shelljs');\nshell.echo('hello world');\n```\n\n## Make tool\n\nA convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script.\n\nExample (CoffeeScript):\n\n```coffeescript\nrequire 'shelljs/make'\n\ntarget.all = ->\n target.bundle()\n target.docs()\n\ntarget.bundle = ->\n cd __dirname\n mkdir 'build'\n cd 'lib'\n (cat '*.js').to '../build/output.js'\n\ntarget.docs = ->\n cd __dirname\n mkdir 'docs'\n cd 'lib'\n for file in ls '*.js'\n text = grep '//@', file # extract special comments\n text.replace '//@', '' # remove comment tags\n text.to 'docs/my_docs.md'\n```\n\nTo run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.\n\n\n\n\n\n\n## Command reference\n\n\nAll commands run synchronously, unless otherwise stated.\n\n\n### cd('dir')\nChanges to directory `dir` for the duration of the script\n\n### pwd()\nReturns the current directory.\n\n### ls([options ,] path [,path ...])\n### ls([options ,] path_array)\nAvailable options:\n\n+ `-R`: recursive\n+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)\n\nExamples:\n\n```javascript\nls('projs/*.js');\nls('-R', '/users/me', '/tmp');\nls('-R', ['/users/me', '/tmp']); // same as above\n```\n\nReturns array of files in the given path, or in current directory if no path provided.\n\n### find(path [,path ...])\n### find(path_array)\nExamples:\n\n```javascript\nfind('src', 'lib');\nfind(['src', 'lib']); // same as above\nfind('.').filter(function(file) { return file.match(/\\.js$/); });\n```\n\nReturns array of all files (however deep) in the given paths.\n\nThe main difference from `ls('-R', path)` is that the resulting file names \ninclude the base directories, e.g. `lib/resources/file1` instead of just `file1`.\n\n### cp([options ,] source [,source ...], dest)\n### cp([options ,] source_array, dest)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\ncp('file1', 'dir1');\ncp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');\ncp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above\n```\n\nCopies files. The wildcard `*` is accepted.\n\n### rm([options ,] file [, file ...])\n### rm([options ,] file_array)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\nrm('-rf', '/tmp/*');\nrm('some_file.txt', 'another_file.txt');\nrm(['some_file.txt', 'another_file.txt']); // same as above\n```\n\nRemoves files. The wildcard `*` is accepted. \n\n### mv(source [, source ...], dest')\n### mv(source_array, dest')\nAvailable options:\n\n+ `f`: force\n\nExamples:\n\n```javascript\nmv('-f', 'file', 'dir/');\nmv('file1', 'file2', 'dir/');\nmv(['file1', 'file2'], 'dir/'); // same as above\n```\n\nMoves files. The wildcard `*` is accepted.\n\n### mkdir([options ,] dir [, dir ...])\n### mkdir([options ,] dir_array)\nAvailable options:\n\n+ `p`: full path (will create intermediate dirs if necessary)\n\nExamples:\n\n```javascript\nmkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');\nmkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above\n```\n\nCreates directories.\n\n### test(expression)\nAvailable expression primaries:\n\n+ `'-b', 'path'`: true if path is a block device\n+ `'-c', 'path'`: true if path is a character device\n+ `'-d', 'path'`: true if path is a directory\n+ `'-e', 'path'`: true if path exists\n+ `'-f', 'path'`: true if path is a regular file\n+ `'-L', 'path'`: true if path is a symboilc link\n+ `'-p', 'path'`: true if path is a pipe (FIFO)\n+ `'-S', 'path'`: true if path is a socket\n\nExamples:\n\n```javascript\nif (test('-d', path)) { /* do something with dir */ };\nif (!test('-f', path)) continue; // skip if it's a regular file\n```\n\nEvaluates expression using the available primaries and returns corresponding value.\n\n### cat(file [, file ...])\n### cat(file_array)\n\nExamples:\n\n```javascript\nvar str = cat('file*.txt');\nvar str = cat('file1', 'file2');\nvar str = cat(['file1', 'file2']); // same as above\n```\n\nReturns a string containing the given file, or a concatenated string\ncontaining the files if more than one file is given (a new line character is\nintroduced between each file). Wildcard `*` accepted.\n\n### 'string'.to(file)\n\nExamples:\n\n```javascript\ncat('input.txt').to('output.txt');\n```\n\nAnalogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as\nthose returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_\n\n### sed([options ,] search_regex, replace_str, file)\nAvailable options:\n\n+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_\n\nExamples:\n\n```javascript\nsed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');\nsed(/.*DELETE_THIS_LINE.*\\n/, '', 'source.js');\n```\n\nReads an input string from `file` and performs a JavaScript `replace()` on the input\nusing the given search regex and replacement string. Returns the new string after replacement.\n\n### grep([options ,] regex_filter, file [, file ...])\n### grep([options ,] regex_filter, file_array)\nAvailable options:\n\n+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria.\n\nExamples:\n\n```javascript\ngrep('-v', 'GLOBAL_VARIABLE', '*.js');\ngrep('GLOBAL_VARIABLE', '*.js');\n```\n\nReads input string from given files and returns a string containing all lines of the \nfile that match the given `regex_filter`. Wildcard `*` accepted.\n\n### which(command)\n\nExamples:\n\n```javascript\nvar nodeExec = which('node');\n```\n\nSearches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.\nReturns string containing the absolute path to the command.\n\n### echo(string [,string ...])\n\nExamples:\n\n```javascript\necho('hello world');\nvar str = echo('hello world');\n```\n\nPrints string to stdout, and returns string with additional utility methods\nlike `.to()`.\n\n### exit(code)\nExits the current process with the given exit code.\n\n### env['VAR_NAME']\nObject containing environment variables (both getter and setter). Shortcut to process.env.\n\n### exec(command [, options] [, callback])\nAvailable options (all `false` by default):\n\n+ `async`: Asynchronous execution. Defaults to true if a callback is provided.\n+ `silent`: Do not echo program output to console.\n\nExamples:\n\n```javascript\nvar version = exec('node --version', {silent:true}).output;\n\nvar child = exec('some_long_running_process', {async:true});\nchild.stdout.on('data', function(data) { \n /* ... do something with data ... */ \n});\n\nexec('some_long_running_process', function(code, output) {\n console.log('Exit code:', code);\n console.log('Program output:', output);\n});\n```\n\nExecutes the given `command` _synchronously_, unless otherwise specified. \nWhen in synchronous mode returns the object `{ code:..., output:... }`, containing the program's \n`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and\nthe `callback` gets the arguments `(code, output)`.\n\n**Note:** For long-lived processes, it's best to run `exec()` asynchronously as\nthe current synchronous implementation uses a lot of CPU. This should be getting\nfixed soon.\n\n## Non-Unix commands\n\n\n### tempdir()\nSearches and returns string containing a writeable, platform-dependent temporary directory.\nFollows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).\n\n### error()\nTests if error occurred in the last command. Returns `null` if no error occurred,\notherwise returns string explaining the error\n\n### silent([state])\nExample:\n\n```javascript\nvar silentState = silent();\nsilent(true);\n/* ... */\nsilent(silentState); // restore old silent state\n```\n\nSuppresses all command output if `state = true`, except for `echo()` calls. \nReturns state if no arguments given.\n\n## Deprecated\n\n\n### exists(path [, path ...])\n### exists(path_array)\n\n_This function is being deprecated. Use `test()` instead._\n\nReturns true if all the given paths exist.\n\n### verbose()\n\n_This function is being deprecated. Use `silent(false) instead.`_\n\nEnables all output (default)\n", - "readmeFilename": "README.md", - "_id": "shelljs@0.0.8", - "_from": "shelljs" -} diff --git a/enyo/tools/node_modules/shelljs/scripts/docs.js b/enyo/tools/node_modules/shelljs/scripts/docs.js deleted file mode 100644 index 68a2138..0000000 --- a/enyo/tools/node_modules/shelljs/scripts/docs.js +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env node -require('../global'); - -echo('Appending docs to README.md'); - -cd(__dirname + '/..'); - -// Extract docs from shell.js -var docs = grep('//@', 'shell.js'); -// Remove '//@' -docs = docs.replace(/\/\/\@ ?/g, ''); -// Append docs to README -sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md'); - -echo('All done.'); diff --git a/enyo/tools/node_modules/shelljs/scripts/run-tests.js b/enyo/tools/node_modules/shelljs/scripts/run-tests.js deleted file mode 100644 index 1268080..0000000 --- a/enyo/tools/node_modules/shelljs/scripts/run-tests.js +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env node -require('../global'); - -var failed = false; - -cd(__dirname + '/../test'); -ls('*.js').forEach(function(file) { - echo('Running test:', file); - if (exec('node '+file).code !== 123) { // 123 avoids false positives (e.g. premature exit) - failed = true; - echo('*** FAILED! (missing return code)'); - } -}); - -if (failed) { - echo(); - echo('WARNING: Some tests did not pass!'); - exit(1); -} else { - echo(); - echo('All tests passed.'); -} diff --git a/enyo/tools/node_modules/shelljs/shell.js b/enyo/tools/node_modules/shelljs/shell.js deleted file mode 100644 index 7881f67..0000000 --- a/enyo/tools/node_modules/shelljs/shell.js +++ /dev/null @@ -1,1513 +0,0 @@ -// -// ShellJS -// Unix shell commands on top of Node's API -// -// Copyright (c) 2012 Artur Adib -// http://github.com/arturadib/shelljs -// - -var fs = require('fs'), - path = require('path'), - util = require('util'), - vm = require('vm'), - child = require('child_process'), - os = require('os'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -var state = { - error: null, - fatal: false, - silent: false, - currentCmd: 'shell.js', - tempDir: null - }, - platform = os.type().match(/^Win/) ? 'win' : 'unix'; - - -//@ -//@ All commands run synchronously, unless otherwise stated. -//@ - - -//@ -//@ ### cd('dir') -//@ Changes to directory `dir` for the duration of the script -function _cd(options, dir) { - if (!dir) - error('directory not specified'); - - if (!fs.existsSync(dir)) - error('no such file or directory: ' + dir); - - if (fs.existsSync(dir) && !fs.statSync(dir).isDirectory()) - error('not a directory: ' + dir); - - process.chdir(dir); -}; -exports.cd = wrap('cd', _cd); - -//@ -//@ ### pwd() -//@ Returns the current directory. -function _pwd(options) { - var pwd = path.resolve(process.cwd()); - return ShellString(pwd); -}; -exports.pwd = wrap('pwd', _pwd); - - -//@ -//@ ### ls([options ,] path [,path ...]) -//@ ### ls([options ,] path_array) -//@ Available options: -//@ -//@ + `-R`: recursive -//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ ls('projs/*.js'); -//@ ls('-R', '/users/me', '/tmp'); -//@ ls('-R', ['/users/me', '/tmp']); // same as above -//@ ``` -//@ -//@ Returns array of files in the given path, or in current directory if no path provided. -function _ls(options, paths) { - options = parseOptions(options, { - 'R': 'recursive', - 'A': 'all', - 'a': 'all_deprecated' - }); - - if (options.all_deprecated) { - // We won't support the -a option as it's hard to image why it's useful - // (it includes '.' and '..' in addition to '.*' files) - // For backwards compatibility we'll dump a deprecated message and proceed as before - log('ls: Option -a is deprecated. Use -A instead'); - options.all = true; - } - - if (!paths) - paths = ['.']; - else if (typeof paths === 'object') - paths = paths; // assume array - else if (typeof paths === 'string') - paths = [].slice.call(arguments, 1); - - var list = []; - - // Conditionally pushes file to list - returns true if pushed, false otherwise - // (e.g. prevents hidden files to be included unless explicitly told so) - function pushFile(file, query) { - // hidden file? - if (path.basename(file)[0] === '.') { - // not explicitly asking for hidden files? - if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1)) - return false; - } - - if (platform === 'win') - file = file.replace(/\\/g, '/'); - - list.push(file); - return true; - } - - paths.forEach(function(p) { - if (fs.existsSync(p)) { - // Simple file? - if (fs.statSync(p).isFile()) { - pushFile(p, p); - return; // continue - } - - // Simple dir? - if (fs.statSync(p).isDirectory()) { - // Iterate over p contents - fs.readdirSync(p).forEach(function(file) { - if (!pushFile(file, p)) - return; - - // Recursive? - if (options.recursive) { - var oldDir = _pwd(); - _cd('', p); - if (fs.statSync(file).isDirectory()) - list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*')); - _cd('', oldDir); - } - }); - return; // continue - } - } - - // p does not exist - possible wildcard present - - var basename = path.basename(p); - var dirname = path.dirname(p); - // Wildcard present on an existing dir? (e.g. '/tmp/*.js') - if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) { - // Escape special regular expression chars - var regexp = basename.replace(/(\^|\$|\(|\)|\<|\>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1'); - // Translates wildcard into regex - regexp = '^' + regexp.replace(/\*/g, '.*') + '$'; - // Iterate over directory contents - fs.readdirSync(dirname).forEach(function(file) { - if (file.match(new RegExp(regexp))) { - if (!pushFile(path.normalize(dirname+'/'+file), basename)) - return; - - // Recursive? - if (options.recursive) { - var pp = dirname + '/' + file; - if (fs.statSync(pp).isDirectory()) - list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*')); - } // recursive - } // if file matches - }); // forEach - return; - } - - error('no such file or directory: ' + p, true); - }); - - return list; -}; -exports.ls = wrap('ls', _ls); - - -//@ -//@ ### find(path [,path ...]) -//@ ### find(path_array) -//@ Examples: -//@ -//@ ```javascript -//@ find('src', 'lib'); -//@ find(['src', 'lib']); // same as above -//@ find('.').filter(function(file) { return file.match(/\.js$/); }); -//@ ``` -//@ -//@ Returns array of all files (however deep) in the given paths. -//@ -//@ The main difference from `ls('-R', path)` is that the resulting file names -//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`. -function _find(options, paths) { - if (!paths) - error('no path specified'); - else if (typeof paths === 'object') - paths = paths; // assume array - else if (typeof paths === 'string') - paths = [].slice.call(arguments, 1); - - var list = []; - - function pushFile(file) { - if (platform === 'win') - file = file.replace(/\\/g, '/'); - list.push(file); - } - - // why not simply do ls('-R', paths)? because the output wouldn't give the base dirs - // to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory - - paths.forEach(function(file) { - pushFile(file); - - if (fs.statSync(file).isDirectory()) { - _ls('-RA', file+'/*').forEach(function(subfile) { - pushFile(subfile); - }); - } - }); - - return list; -} -exports.find = wrap('find', _find); - - -//@ -//@ ### cp([options ,] source [,source ...], dest) -//@ ### cp([options ,] source_array, dest) -//@ Available options: -//@ -//@ + `-f`: force -//@ + `-r, -R`: recursive -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cp('file1', 'dir1'); -//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); -//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above -//@ ``` -//@ -//@ Copies files. The wildcard `*` is accepted. -function _cp(options, sources, dest) { - options = parseOptions(options, { - 'f': 'force', - 'R': 'recursive', - 'r': 'recursive' - }); - - // Get sources, dest - if (arguments.length < 3) { - error('missing and/or '); - } else if (arguments.length > 3) { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } else if (typeof sources === 'string') { - sources = [sources]; - } else if ('length' in sources) { - sources = sources; // no-op for array - } else { - error('invalid arguments'); - } - - // Dest is not existing dir, but multiple sources given - if ((!fs.existsSync(dest) || !fs.statSync(dest).isDirectory()) && sources.length > 1) - error('dest is not a directory (too many sources)'); - - // Dest is an existing file, but no -f given - if (fs.existsSync(dest) && fs.statSync(dest).isFile() && !options.force) - error('dest file already exists: ' + dest); - - // Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*" - // (see Github issue #15) - if (options.recursive) { - sources.forEach(function(src, i) { - if (src[src.length - 1] === '/') - sources[i] += '*'; - }); - } - - sources = expand(sources); - - sources.forEach(function(src) { - if (!fs.existsSync(src)) { - error('no such file or directory: '+src, true); - return; // skip file - } - - // If here, src exists - - if (fs.statSync(src).isDirectory()) { - if (!options.recursive) { - // Non-Recursive - log(src + ' is a directory (not copied)'); - } else { - // Recursive - // 'cp /a/source dest' should create 'source' in 'dest' - var newDest = dest+'/'+path.basename(src), - checkDir = fs.statSync(src); - try { - fs.mkdirSync(newDest, checkDir.mode); - } catch (e) { - //if the directory already exists, that's okay - if (e.code !== 'EEXIST') throw e; - } - cpdirSyncRecursive(src, newDest, {force: options.force}); - } - return; // done with dir - } - - // If here, src is a file - - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) - thisDest = path.normalize(dest + '/' + path.basename(src)); - - if (fs.existsSync(thisDest) && !options.force) { - error('dest file already exists: ' + thisDest, true); - return; // skip file - } - - copyFileSync(src, thisDest); - }); // forEach(src) -}; // cp -exports.cp = wrap('cp', _cp); - -//@ -//@ ### rm([options ,] file [, file ...]) -//@ ### rm([options ,] file_array) -//@ Available options: -//@ -//@ + `-f`: force -//@ + `-r, -R`: recursive -//@ -//@ Examples: -//@ -//@ ```javascript -//@ rm('-rf', '/tmp/*'); -//@ rm('some_file.txt', 'another_file.txt'); -//@ rm(['some_file.txt', 'another_file.txt']); // same as above -//@ ``` -//@ -//@ Removes files. The wildcard `*` is accepted. -function _rm(options, files) { - options = parseOptions(options, { - 'f': 'force', - 'r': 'recursive', - 'R': 'recursive' - }); - if (!files) - error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 1); - // if it's array leave it as it is - - files = expand(files); - - files.forEach(function(file) { - if (!fs.existsSync(file)) { - // Path does not exist, no force flag given - if (!options.force) - error('no such file or directory: '+file, true); - - return; // skip file - } - - // If here, path exists - - // Remove simple file - if (fs.statSync(file).isFile()) { - - // Do not check for file writing permissions - if (options.force) { - _unlinkSync(file); - return; - } - - if (isWriteable(file)) - _unlinkSync(file); - else - error('permission denied: '+file, true); - - return; - } // simple file - - // Path is an existing directory, but no -r flag given - if (fs.statSync(file).isDirectory() && !options.recursive) { - error('path is a directory', true); - return; // skip path - } - - // Recursively remove existing directory - if (fs.statSync(file).isDirectory() && options.recursive) { - rmdirSyncRecursive(file, options.force); - } - }); // forEach(file) -}; // rm -exports.rm = wrap('rm', _rm); - -//@ -//@ ### mv(source [, source ...], dest') -//@ ### mv(source_array, dest') -//@ Available options: -//@ -//@ + `f`: force -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mv('-f', 'file', 'dir/'); -//@ mv('file1', 'file2', 'dir/'); -//@ mv(['file1', 'file2'], 'dir/'); // same as above -//@ ``` -//@ -//@ Moves files. The wildcard `*` is accepted. -function _mv(options, sources, dest) { - options = parseOptions(options, { - 'f': 'force' - }); - - // Get sources, dest - if (arguments.length < 3) { - error('missing and/or '); - } else if (arguments.length > 3) { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } else if (typeof sources === 'string') { - sources = [sources]; - } else if ('length' in sources) { - sources = sources; // no-op for array - } else { - error('invalid arguments'); - } - - sources = expand(sources); - - // Dest is not existing dir, but multiple sources given - if ((!fs.existsSync(dest) || !fs.statSync(dest).isDirectory()) && sources.length > 1) - error('dest is not a directory (too many sources)'); - - // Dest is an existing file, but no -f given - if (fs.existsSync(dest) && fs.statSync(dest).isFile() && !options.force) - error('dest file already exists: ' + dest); - - sources.forEach(function(src) { - if (!fs.existsSync(src)) { - error('no such file or directory: '+src, true); - return; // skip file - } - - // If here, src exists - - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) - thisDest = path.normalize(dest + '/' + path.basename(src)); - - if (fs.existsSync(thisDest) && !options.force) { - error('dest file already exists: ' + thisDest, true); - return; // skip file - } - - if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { - error('cannot move to self: '+src, true); - return; // skip file - } - - fs.renameSync(src, thisDest); - }); // forEach(src) -}; // mv -exports.mv = wrap('mv', _mv); - -//@ -//@ ### mkdir([options ,] dir [, dir ...]) -//@ ### mkdir([options ,] dir_array) -//@ Available options: -//@ -//@ + `p`: full path (will create intermediate dirs if necessary) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); -//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above -//@ ``` -//@ -//@ Creates directories. -function _mkdir(options, dirs) { - options = parseOptions(options, { - 'p': 'fullpath' - }); - if (!dirs) - error('no paths given'); - - if (typeof dirs === 'string') - dirs = [].slice.call(arguments, 1); - // if it's array leave it as it is - - dirs.forEach(function(dir) { - if (fs.existsSync(dir)) { - if (!options.fullpath) - error('path already exists: ' + dir, true); - return; // skip dir - } - - // Base dir does not exist, and no -p option given - var baseDir = path.dirname(dir); - if (!fs.existsSync(baseDir) && !options.fullpath) { - error('no such file or directory: ' + baseDir, true); - return; // skip dir - } - - if (options.fullpath) - mkdirSyncRecursive(dir); - else - fs.mkdirSync(dir, 0777); - }); -}; // mkdir -exports.mkdir = wrap('mkdir', _mkdir); - -//@ -//@ ### test(expression) -//@ Available expression primaries: -//@ -//@ + `'-b', 'path'`: true if path is a block device -//@ + `'-c', 'path'`: true if path is a character device -//@ + `'-d', 'path'`: true if path is a directory -//@ + `'-e', 'path'`: true if path exists -//@ + `'-f', 'path'`: true if path is a regular file -//@ + `'-L', 'path'`: true if path is a symboilc link -//@ + `'-p', 'path'`: true if path is a pipe (FIFO) -//@ + `'-S', 'path'`: true if path is a socket -//@ -//@ Examples: -//@ -//@ ```javascript -//@ if (test('-d', path)) { /* do something with dir */ }; -//@ if (!test('-f', path)) continue; // skip if it's a regular file -//@ ``` -//@ -//@ Evaluates expression using the available primaries and returns corresponding value. -function _test(options, path) { - if (!path) - error('no path given'); - - // hack - only works with unary primaries - options = parseOptions(options, { - 'b': 'block', - 'c': 'character', - 'd': 'directory', - 'e': 'exists', - 'f': 'file', - 'L': 'link', - 'p': 'pipe', - 'S': 'socket' - }); - - var canInterpret = false; - for (var key in options) - if (options[key] === true) { - canInterpret = true; - break; - } - - if (!canInterpret) - error('could not interpret expression'); - - if (!fs.existsSync(path)) - return false; - - if (options.exists) - return true; - - if (options.link) - return fs.lstatSync(path).isSymbolicLink(); - - var stats = fs.statSync(path); - - if (options.block) - return stats.isBlockDevice(); - - if (options.character) - return stats.isCharacterDevice(); - - if (options.directory) - return stats.isDirectory(); - - if (options.file) - return stats.isFile(); - - if (options.pipe) - return stats.isFIFO(); - - if (options.socket) - return stats.isSocket() -}; // test -exports.test = wrap('test', _test); - - -//@ -//@ ### cat(file [, file ...]) -//@ ### cat(file_array) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var str = cat('file*.txt'); -//@ var str = cat('file1', 'file2'); -//@ var str = cat(['file1', 'file2']); // same as above -//@ ``` -//@ -//@ Returns a string containing the given file, or a concatenated string -//@ containing the files if more than one file is given (a new line character is -//@ introduced between each file). Wildcard `*` accepted. -function _cat(options, files) { - var cat = ''; - - if (!files) - error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 1); - // if it's array leave it as it is - - files = expand(files); - - files.forEach(function(file) { - if (!fs.existsSync(file)) - error('no such file or directory: ' + file); - - cat += fs.readFileSync(file, 'utf8') + '\n'; - }); - - if (cat[cat.length-1] === '\n') - cat = cat.substring(0, cat.length-1); - - return ShellString(cat); -}; -exports.cat = wrap('cat', _cat); - -//@ -//@ ### 'string'.to(file) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cat('input.txt').to('output.txt'); -//@ ``` -//@ -//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as -//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ -function _to(options, file) { - if (!file) - error('wrong arguments'); - - if (!fs.existsSync( path.dirname(file) )) - error('no such file or directory: ' + path.dirname(file)); - - try { - fs.writeFileSync(file, this.toString(), 'utf8'); - } catch(e) { - error('could not write to file (code '+e.code+'): '+file, true); - } -}; -// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings. -// For now, this is a dummy function to bookmark places we need such strings -function ShellString(str) { - return str; -} -String.prototype.to = wrap('to', _to); - -//@ -//@ ### sed([options ,] search_regex, replace_str, file) -//@ Available options: -//@ -//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ -//@ -//@ Examples: -//@ -//@ ```javascript -//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); -//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); -//@ ``` -//@ -//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input -//@ using the given search regex and replacement string. Returns the new string after replacement. -function _sed(options, regex, replacement, file) { - options = parseOptions(options, { - 'i': 'inplace' - }); - - if (typeof replacement === 'string') - replacement = replacement; // no-op - else if (typeof replacement === 'number') - replacement = replacement.toString(); // fallback - else - error('invalid replacement string'); - - if (!file) - error('no file given'); - - if (!fs.existsSync(file)) - error('no such file or directory: ' + file); - - var result = fs.readFileSync(file, 'utf8').replace(regex, replacement); - if (options.inplace) - fs.writeFileSync(file, result, 'utf8'); - - return ShellString(result); -}; -exports.sed = wrap('sed', _sed); - -//@ -//@ ### grep([options ,] regex_filter, file [, file ...]) -//@ ### grep([options ,] regex_filter, file_array) -//@ Available options: -//@ -//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); -//@ grep('GLOBAL_VARIABLE', '*.js'); -//@ ``` -//@ -//@ Reads input string from given files and returns a string containing all lines of the -//@ file that match the given `regex_filter`. Wildcard `*` accepted. -function _grep(options, regex, files) { - options = parseOptions(options, { - 'v': 'inverse' - }); - - if (!files) - error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 2); - // if it's array leave it as it is - - files = expand(files); - - var grep = ''; - files.forEach(function(file) { - if (!fs.existsSync(file)) { - error('no such file or directory: ' + file, true); - return; - } - - var contents = fs.readFileSync(file, 'utf8'), - lines = contents.split(/\r*\n/); - lines.forEach(function(line) { - var matched = line.match(regex); - if ((options.inverse && !matched) || (!options.inverse && matched)) - grep += line + '\n'; - }); - }); - - return ShellString(grep); -}; -exports.grep = wrap('grep', _grep); - - -//@ -//@ ### which(command) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var nodeExec = which('node'); -//@ ``` -//@ -//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. -//@ Returns string containing the absolute path to the command. -function _which(options, cmd) { - if (!cmd) - error('must specify command'); - - var pathEnv = process.env.path || process.env.Path || process.env.PATH, - pathArray = splitPath(pathEnv), - where = null; - - // No relative/absolute paths provided? - if (cmd.search(/\//) === -1) { - // Search for command in PATH - pathArray.forEach(function(dir) { - if (where) - return; // already found it - - var attempt = path.resolve(dir + '/' + cmd); - if (fs.existsSync(attempt)) { - where = attempt; - return; - } - - if (platform === 'win') { - var baseAttempt = attempt; - attempt = baseAttempt + '.exe'; - if (fs.existsSync(attempt)) { - where = attempt; - return; - } - attempt = baseAttempt + '.cmd'; - if (fs.existsSync(attempt)) { - where = attempt; - return; - } - attempt = baseAttempt + '.bat'; - if (fs.existsSync(attempt)) { - where = attempt; - return; - } - } // if 'win' - }); - } - - // Command not found anywhere? - if (!fs.existsSync(cmd) && !where) - return null; - - where = where || path.resolve(cmd); - - return ShellString(where); -}; -exports.which = wrap('which', _which); - -//@ -//@ ### echo(string [,string ...]) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ echo('hello world'); -//@ var str = echo('hello world'); -//@ ``` -//@ -//@ Prints string to stdout, and returns string with additional utility methods -//@ like `.to()`. -function _echo() { - var messages = [].slice.call(arguments, 0); - console.log.apply(this, messages); - return ShellString(messages.join(' ')); -}; -exports.echo = _echo; // don't wrap() as it could parse '-options' - -//@ -//@ ### exit(code) -//@ Exits the current process with the given exit code. -exports.exit = process.exit; - -//@ -//@ ### env['VAR_NAME'] -//@ Object containing environment variables (both getter and setter). Shortcut to process.env. -exports.env = process.env; - -//@ -//@ ### exec(command [, options] [, callback]) -//@ Available options (all `false` by default): -//@ -//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided. -//@ + `silent`: Do not echo program output to console. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var version = exec('node --version', {silent:true}).output; -//@ -//@ var child = exec('some_long_running_process', {async:true}); -//@ child.stdout.on('data', function(data) { -//@ /* ... do something with data ... */ -//@ }); -//@ -//@ exec('some_long_running_process', function(code, output) { -//@ console.log('Exit code:', code); -//@ console.log('Program output:', output); -//@ }); -//@ ``` -//@ -//@ Executes the given `command` _synchronously_, unless otherwise specified. -//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's -//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and -//@ the `callback` gets the arguments `(code, output)`. -//@ -//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as -//@ the current synchronous implementation uses a lot of CPU. This should be getting -//@ fixed soon. -function _exec(command, options, callback) { - if (!command) - error('must specify command'); - - if (typeof options === 'function') { - callback = options; - options = { async: true }; - } - - options = extend({ - silent: state.silent, - async: false - }, options); - - if (options.async) - return execAsync(command, options, callback); - else - return execSync(command, options); -}; -exports.exec = wrap('exec', _exec, {notUnix:true}); - - - - -//@ -//@ ## Non-Unix commands -//@ - - - - - - -//@ -//@ ### tempdir() -//@ Searches and returns string containing a writeable, platform-dependent temporary directory. -//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). -exports.tempdir = wrap('tempdir', tempDir); - - -//@ -//@ ### error() -//@ Tests if error occurred in the last command. Returns `null` if no error occurred, -//@ otherwise returns string explaining the error -exports.error = function() { - return state.error; -} - -//@ -//@ ### silent([state]) -//@ Example: -//@ -//@ ```javascript -//@ var silentState = silent(); -//@ silent(true); -//@ /* ... */ -//@ silent(silentState); // restore old silent state -//@ ``` -//@ -//@ Suppresses all command output if `state = true`, except for `echo()` calls. -//@ Returns state if no arguments given. -exports.silent = function(_state) { - if (typeof _state !== 'boolean') - return state.silent; - - state.silent = _state; -} - - -//@ -//@ ## Deprecated -//@ - - - - -//@ -//@ ### exists(path [, path ...]) -//@ ### exists(path_array) -//@ -//@ _This function is being deprecated. Use `test()` instead._ -//@ -//@ Returns true if all the given paths exist. -function _exists(options, paths) { - deprecate('exists', 'Use test() instead.'); - - if (!paths) - error('no paths given'); - - if (typeof paths === 'string') - paths = [].slice.call(arguments, 1); - // if it's array leave it as it is - - var exists = true; - paths.forEach(function(p) { - if (!fs.existsSync(p)) - exists = false; - }); - - return exists; -}; -exports.exists = wrap('exists', _exists); - - -//@ -//@ ### verbose() -//@ -//@ _This function is being deprecated. Use `silent(false) instead.`_ -//@ -//@ Enables all output (default) -exports.verbose = function() { - deprecate('verbose', 'Use silent(false) instead.'); - - state.silent = false; -} - - - - - - - - - - -//////////////////////////////////////////////////////////////////////////////////////////////// -// -// Auxiliary functions (internal use only) -// - -function log() { - if (!state.silent) - console.log.apply(this, arguments); -} - -function deprecate(what, msg) { - console.log('*** ShellJS.'+what+': This function is deprecated.', msg); -} - -function write(msg) { - if (!state.silent) - process.stdout.write(msg); -} - -// Shows error message. Throws unless '_continue = true'. -function error(msg, _continue) { - if (state.error === null) - state.error = ''; - state.error += state.currentCmd + ': ' + msg + '\n'; - - log(state.error); - - if (!_continue) - throw ''; -} - -// Returns {'alice': true, 'bob': false} when passed: -// parseOptions('-a', {'a':'alice', 'b':'bob'}); -function parseOptions(str, map) { - if (!map) - error('parseOptions() internal error: no map given'); - - // All options are false by default - var options = {}; - for (var letter in map) - options[map[letter]] = false; - - if (!str) - return options; // defaults - - if (typeof str !== 'string') - error('parseOptions() internal error: wrong str'); - - // e.g. match[1] = 'Rf' for str = '-Rf' - var match = str.match(/^\-(.+)/); - if (!match) - return options; - - // e.g. chars = ['R', 'f'] - var chars = match[1].split(''); - - chars.forEach(function(char) { - if (char in map) - options[map[char]] = true; - else - error('option not recognized: '+char); - }); - - return options; -} - -// Common wrapper for all Unix-like commands -function wrap(cmd, fn, options) { - return function() { - var retValue = null; - - state.currentCmd = cmd; - state.error = null; - - try { - var args = [].slice.call(arguments, 0); - - if (options && options.notUnix) { - retValue = fn.apply(this, args); - } else { - if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-') - args.unshift(''); // only add dummy option if '-option' not already present - retValue = fn.apply(this, args); - } - } catch (e) { - if (!state.error) { - // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... - console.log('shell.js: internal error'); - console.log(e.stack || e); - process.exit(1); - } - if (state.fatal) - throw e; - } - - state.currentCmd = 'shell.js'; - return retValue; - } -} // wrap - -// Buffered file copy, synchronous -// (Using readFileSync() + writeFileSync() could easily cause a memory overflow -// with large files) -function copyFileSync(srcFile, destFile) { - if (!fs.existsSync(srcFile)) - error('copyFileSync: no such file or directory: ' + srcFile); - - var BUF_LENGTH = 64*1024, - buf = new Buffer(BUF_LENGTH), - bytesRead = BUF_LENGTH, - pos = 0, - fdr = null, - fdw = null; - - try { - fdr = fs.openSync(srcFile, 'r'); - } catch(e) { - error('copyFileSync: could not read src file ('+srcFile+')'); - } - - try { - fdw = fs.openSync(destFile, 'w'); - } catch(e) { - error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile); - } - - while (bytesRead === BUF_LENGTH) { - bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos); - fs.writeSync(fdw, buf, 0, bytesRead); - pos += bytesRead; - } - - fs.closeSync(fdr); - fs.closeSync(fdw); -} - -// Recursively copies 'sourceDir' into 'destDir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function cpdirSyncRecursive(sourceDir, destDir, opts) { - if (!opts) opts = {}; - - /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ - var checkDir = fs.statSync(sourceDir); - try { - fs.mkdirSync(destDir, checkDir.mode); - } catch (e) { - //if the directory already exists, that's okay - if (e.code !== 'EEXIST') throw e; - } - - var files = fs.readdirSync(sourceDir); - - for(var i = 0; i < files.length; i++) { - var currFile = fs.lstatSync(sourceDir + "/" + files[i]); - - if (currFile.isDirectory()) { - /* recursion this thing right on back. */ - cpdirSyncRecursive(sourceDir + "/" + files[i], destDir + "/" + files[i], opts); - } else if (currFile.isSymbolicLink()) { - var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]); - fs.symlinkSync(symlinkFull, destDir + "/" + files[i]); - } else { - /* At this point, we've hit a file actually worth copying... so copy it on over. */ - if (fs.existsSync(destDir + "/" + files[i]) && !opts.force) { - log('skipping existing file: ' + files[i]); - } else { - copyFileSync(sourceDir + "/" + files[i], destDir + "/" + files[i]); - } - } - - } // for files -}; // cpdirSyncRecursive - -// Recursively removes 'dir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function rmdirSyncRecursive(dir, force) { - var files; - - files = fs.readdirSync(dir); - - // Loop through and delete everything in the sub-tree after checking it - for(var i = 0; i < files.length; i++) { - var file = dir + "/" + files[i], - currFile = fs.lstatSync(file); - - if(currFile.isDirectory()) { // Recursive function back to the beginning - rmdirSyncRecursive(file, force); - } - - else if(currFile.isSymbolicLink()) { // Unlink symlinks - if (force || isWriteable(file)) { - try { - _unlinkSync(file); - } catch (e) { - error('could not remove file (code '+e.code+'): ' + file, true); - } - } - } - - else // Assume it's a file - perhaps a try/catch belongs here? - if (force || isWriteable(file)) { - try { - _unlinkSync(file); - } catch (e) { - error('could not remove file (code '+e.code+'): ' + file, true); - } - } - } - - // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. - // Huzzah for the shopkeep. - - var result; - try { - result = fs.rmdirSync(dir); - } catch(e) { - error('could not remove directory (code '+e.code+'): ' + dir, true); - } - - return result; -}; // rmdirSyncRecursive - -// Recursively creates 'dir' -function mkdirSyncRecursive(dir) { - var baseDir = path.dirname(dir); - - // Base dir exists, no recursion necessary - if (fs.existsSync(baseDir)) { - fs.mkdirSync(dir, 0777); - return; - } - - // Base dir does not exist, go recursive - mkdirSyncRecursive(baseDir); - - // Base dir created, can create dir - fs.mkdirSync(dir, 0777); -}; - -// e.g. 'makerjs_a5f185d0443ca...' -function randomFileName() { - function randomHash(count) { - if (count === 1) - return parseInt(16*Math.random()).toString(16); - else { - var hash = ''; - for (var i=0; i&1'; // works on both win/unix - - var script = - "var child = require('child_process'), \ - fs = require('fs'); \ - child.exec('"+escape(cmd)+"', {env: process.env}, function(err) { \ - fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0'); \ - });"; - - if (fs.existsSync(scriptFile)) _unlinkSync(scriptFile); - if (fs.existsSync(stdoutFile)) _unlinkSync(stdoutFile); - if (fs.existsSync(codeFile)) _unlinkSync(codeFile); - - fs.writeFileSync(scriptFile, script); - child.exec('node '+scriptFile, { - env: process.env, - cwd: exports.pwd() - }); - - // The wait loop - // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage - // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing - // CPU usage, though apparently not so much on Windows) - while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }; - while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }; - - // At this point codeFile exists, but it's not necessarily flushed yet. - // Keep reading it until it is. - var code = parseInt(''); - while (isNaN(code)) - code = parseInt(fs.readFileSync(codeFile, 'utf8')); - - var stdout = fs.readFileSync(stdoutFile, 'utf8'); - - // No biggie if we can't erase the files now -- they're in a temp dir anyway - try { _unlinkSync(scriptFile); } catch(e) {}; - try { _unlinkSync(stdoutFile); } catch(e) {}; - try { _unlinkSync(codeFile); } catch(e) {}; - try { _unlinkSync(sleepFile); } catch(e) {}; - - // True if successful, false if not - var obj = { - code: code, - output: stdout - }; - return obj; -} // execSync() - -// Expands wildcards with matching file names. For a given array of file names 'list', returns -// another array containing all file names as per ls(list[i]). -// For example: -// expand(['file*.js']) = ['file1.js', 'file2.js', ...] -// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) -function expand(list) { - var expanded = []; - list.forEach(function(listEl) { - // Wildcard present? - if (listEl.search(/\*/) > -1) { - _ls('', listEl).forEach(function(file) { - expanded.push(file); - }); - } else { - expanded.push(listEl); - } - }); - return expanded; -} - -// Cross-platform method for splitting environment PATH variables -function splitPath(p) { - if (!p) - return []; - - if (platform === 'win') - return p.split(';'); - else - return p.split(':'); -} - -// extend(target_obj, source_obj1 [, source_obj2 ...]) -// Shallow extend, e.g.: -// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3} -function extend(target) { - var sources = [].slice.call(arguments, 1); - sources.forEach(function(source) { - for (var key in source) - target[key] = source[key]; - }); - - return target; -} - -// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. -// file can be unlinked even if it's read-only, see joyent/node#3006 -function _unlinkSync(file) { - try { - fs.unlinkSync(file); - } catch(e) { - // Try to override file permission - if (e.code === 'EPERM') { - fs.chmodSync(file, '0666'); - fs.unlinkSync(file); - } else { - throw e; - } - } -} - -// Hack to determine if file has write permissions for current user -// Avoids having to check user, group, etc, but it's probably slow -function isWriteable(file) { - var writePermission = true; - try { - var __fd = fs.openSync(file, 'a'); - fs.closeSync(__fd); - } catch(e) { - writePermission = false; - } - - return writePermission; -} diff --git a/enyo/tools/node_modules/shelljs/test/.npmignore b/enyo/tools/node_modules/shelljs/test/.npmignore deleted file mode 100644 index a1632ab..0000000 --- a/enyo/tools/node_modules/shelljs/test/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -tmp/ - diff --git a/enyo/tools/node_modules/shelljs/test/cat.js b/enyo/tools/node_modules/shelljs/test/cat.js deleted file mode 100644 index cd73543..0000000 --- a/enyo/tools/node_modules/shelljs/test/cat.js +++ /dev/null @@ -1,57 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -// save current dir -var cur = shell.pwd(); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.cat(); -assert.ok(shell.error()); - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -shell.cat('/adsfasdf'); // file does not exist -assert.ok(shell.error()); - -// -// Valids -// - -// simple -var result = shell.cat('resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, 'test1'); - -// multiple files -var result = shell.cat('resources/file2', 'resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, 'test2\ntest1'); - -// multiple files, array syntax -var result = shell.cat(['resources/file2', 'resources/file1']); -assert.equal(shell.error(), null); -assert.equal(result, 'test2\ntest1'); - -var result = shell.cat('resources/file*.txt'); -assert.equal(shell.error(), null); -assert.ok(result.search('test1') > -1); // file order might be random -assert.ok(result.search('test2') > -1); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/cd.js b/enyo/tools/node_modules/shelljs/test/cd.js deleted file mode 100644 index 0852ec7..0000000 --- a/enyo/tools/node_modules/shelljs/test/cd.js +++ /dev/null @@ -1,64 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -// save current dir -var cur = shell.pwd(); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.cd(); -assert.ok(shell.error()); - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -shell.cd('/adsfasdf'); // dir does not exist -assert.ok(shell.error()); - -assert.equal(fs.existsSync('resources/file1'), true); // sanity check -shell.cd('resources/file1'); // file, not dir -assert.ok(shell.error()); - -// -// Valids -// - -shell.cd(cur); -shell.cd('tmp'); -assert.equal(shell.error(), null); -assert.equal(path.basename(process.cwd()), 'tmp'); - -shell.cd(cur); -shell.cd('/'); -assert.equal(shell.error(), null); -assert.equal(process.cwd(), path.resolve('/')); - -// cd + other commands - -shell.cd(cur); -shell.rm('-f', 'tmp/*'); -assert.equal(fs.existsSync('tmp/file1'), false); -shell.cd('resources'); -assert.equal(shell.error(), null); -shell.cp('file1', '../tmp'); -assert.equal(shell.error(), null); -shell.cd('../tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), true); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/cp.js b/enyo/tools/node_modules/shelljs/test/cp.js deleted file mode 100644 index 7e32c64..0000000 --- a/enyo/tools/node_modules/shelljs/test/cp.js +++ /dev/null @@ -1,130 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.cp(); -assert.ok(shell.error()); - -shell.cp('file1'); -assert.ok(shell.error()); - -shell.cp('-f'); -assert.ok(shell.error()); - -shell.rm('-rf', 'tmp/*'); -shell.cp('-@', 'resources/file1', 'tmp/file1'); // option not supported, files OK -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/file1'), false); - -shell.cp('-Z', 'asdfasdf', 'tmp/file2'); // option not supported, files NOT OK -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/file2'), false); - -shell.cp('asdfasdf', 'tmp'); // source does not exist -assert.ok(shell.error()); -assert.equal(numLines(shell.error()), 1); -assert.equal(fs.existsSync('tmp/asdfasdf'), false); - -shell.cp('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist -assert.ok(shell.error()); -assert.equal(numLines(shell.error()), 2); -assert.equal(fs.existsSync('tmp/asdfasdf1'), false); -assert.equal(fs.existsSync('tmp/asdfasdf2'), false); - -shell.cp('asdfasdf1', 'asdfasdf2', 'resources/file1'); // too many sources (dest is file) -assert.ok(shell.error()); - -shell.cp('resources/file1', 'resources/file2'); // dest already exists -assert.ok(shell.error()); - -shell.cp('resources/file1', 'resources/file2', 'tmp/a_file'); // too many sources -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/a_file'), false); - -// -// Valids -// - -// simple - to dir -shell.cp('resources/file1', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), true); - -// simple - to file -shell.cp('resources/file2', 'tmp/file2'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file2'), true); - -// simple - file list -shell.rm('-rf', 'tmp/*'); -shell.cp('resources/file1', 'resources/file2', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), true); -assert.equal(fs.existsSync('tmp/file2'), true); - -// simple - file list, array syntax -shell.rm('-rf', 'tmp/*'); -shell.cp(['resources/file1', 'resources/file2'], 'tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), true); -assert.equal(fs.existsSync('tmp/file2'), true); - -shell.cp('resources/file2', 'tmp/file3'); -assert.equal(fs.existsSync('tmp/file3'), true); -shell.cp('-f', 'resources/file2', 'tmp/file3'); // file exists, but -f specified -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file3'), true); - -// wildcard -shell.rm('tmp/file1', 'tmp/file2'); -shell.cp('resources/file*', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), true); -assert.equal(fs.existsSync('tmp/file2'), true); - -//recursive, nothing exists -shell.rm('-rf', 'tmp/*'); -shell.cp('-R', 'resources/cp', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(JSON.stringify(shell.ls('-R', 'resources/cp')), JSON.stringify(shell.ls('-R', 'tmp/cp'))); - -//recursive, nothing exists, source ends in '/' (see Github issue #15) -shell.rm('-rf', 'tmp/*'); -shell.cp('-R', 'resources/cp/', 'tmp/'); -assert.equal(shell.error(), null); -assert.equal(JSON.stringify(shell.ls('-R', 'resources/cp')), JSON.stringify(shell.ls('-R', 'tmp'))); - -//recursive, everything exists, no force flag -shell.rm('-rf', 'tmp/*') -shell.cp('-R', 'resources/cp', 'tmp'); -shell.cp('-R', 'resources/cp', 'tmp'); -assert.equal(shell.error(), null); // crash test only - -//recursive, everything exists, with force flag -shell.rm('-rf', 'tmp/*') -shell.cp('-R', 'resources/cp', 'tmp'); -'changing things around'.to('tmp/cp/dir_a/z'); -assert.notEqual(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // before cp -shell.cp('-Rf', 'resources/cp', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // after cp - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/echo.js b/enyo/tools/node_modules/shelljs/test/echo.js deleted file mode 100644 index b6f2db1..0000000 --- a/enyo/tools/node_modules/shelljs/test/echo.js +++ /dev/null @@ -1,50 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'), - child = require('child_process'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Valids -// - - -// From here on we use child.exec() to intercept the stdout - - -// simple test with defaults -shell.mkdir('-p', 'tmp'); -var file = 'tmp/tempscript'+Math.random()+'.js', - script = 'require(\'../../global.js\'); echo("-asdf", "111");'; // test '-' bug (see issue #20) -script.to(file); -child.exec('node '+file, function(err, stdout, stderr) { - assert.ok(stdout === '-asdf 111\n' || stdout === '-asdf 111\nundefined\n'); // 'undefined' for v0.4 - - // simple test with silent(true) - shell.mkdir('-p', 'tmp'); - var file = 'tmp/tempscript'+Math.random()+'.js', - script = 'require(\'../../global.js\'); silent(true); echo(555);'; - script.to(file); - child.exec('node '+file, function(err, stdout, stderr) { - assert.ok(stdout === '555\n' || stdout === '555\nundefined\n'); // 'undefined' for v0.4 - - theEnd(); - }); -}); - -function theEnd() { - shell.exit(123); -} diff --git a/enyo/tools/node_modules/shelljs/test/env.js b/enyo/tools/node_modules/shelljs/test/env.js deleted file mode 100644 index 813ce27..0000000 --- a/enyo/tools/node_modules/shelljs/test/env.js +++ /dev/null @@ -1,19 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'); - -shell.silent(true); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Valids -// - -assert.equal(shell.env['PATH'], process.env['PATH']); - -shell.env['MAKERJS_TEST'] = 'hello world'; -assert.equal(shell.env['MAKERJS_TEST'], process.env['MAKERJS_TEST']); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/exec.js b/enyo/tools/node_modules/shelljs/test/exec.js deleted file mode 100644 index 473281b..0000000 --- a/enyo/tools/node_modules/shelljs/test/exec.js +++ /dev/null @@ -1,93 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'), - child = require('child_process'); - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -// -// Invalids -// - -shell.exec(); -assert.ok(shell.error()); - -var result = shell.exec('asdfasdf'); // could not find command -assert.ok(result.code > 0); - - -// -// Valids -// - -// -// sync -// - -// check if stdout goes to output -var result = shell.exec('node -e \"console.log(1234);\"'); -assert.equal(shell.error(), null); -assert.equal(result.code, 0); -assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 - -// check if stderr goes to output -var result = shell.exec('node -e \"console.error(1234);\"'); -assert.equal(shell.error(), null); -assert.equal(result.code, 0); -assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 - -// check if stdout + stderr go to output -var result = shell.exec('node -e \"console.error(1234); console.log(666);\"'); -assert.equal(shell.error(), null); -assert.equal(result.code, 0); -assert.ok(result.output === '1234\n666\n' || result.output === '1234\n666\nundefined\n'); // 'undefined' for v0.4 - -// check exit code -var result = shell.exec('node -e \"process.exit(12);\"'); -assert.equal(shell.error(), null); -assert.equal(result.code, 12); - -// interaction with cd -shell.cd('resources/external'); -var result = shell.exec('node node_script.js'); -assert.equal(shell.error(), null); -assert.equal(result.code, 0); -assert.equal(result.output, 'node_script_1234\n'); -shell.cd('../..'); - -// -// async -// - -// no callback -var c = shell.exec('node -e \"console.log(1234)\"', {async:true}); -assert.equal(shell.error(), null); -assert.ok('stdout' in c, 'async exec returns child process object'); - -// -// callback as 2nd argument -// -shell.exec('node -e \"console.log(5678);\"', function(code, output) { - assert.equal(code, 0); - assert.ok(output === '5678\n' || output === '5678\nundefined\n'); // 'undefined' for v0.4 - - // - // callback as 3rd argument - // - shell.exec('node -e \"console.log(5566);\"', {async:true}, function(code, output) { - assert.equal(code, 0); - assert.ok(output === '5566\n' || output === '5566\nundefined\n'); // 'undefined' for v0.4 - - shell.exit(123); - - }); - -}); - -assert.equal(shell.error(), null); diff --git a/enyo/tools/node_modules/shelljs/test/find.js b/enyo/tools/node_modules/shelljs/test/find.js deleted file mode 100644 index 423b82a..0000000 --- a/enyo/tools/node_modules/shelljs/test/find.js +++ /dev/null @@ -1,56 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -var result = shell.find(); // no paths given -assert.ok(shell.error()); - -// -// Valids -// - -// current path -shell.cd('resources/find'); -var result = shell.find('.'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('.hidden') > -1, true); -assert.equal(result.indexOf('dir1/dir11/a_dir11') > -1, true); -assert.equal(result.length, 10); -shell.cd('../..') - -// simple path -var result = shell.find('resources/find'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/find/.hidden') > -1, true); -assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); -assert.equal(result.length, 10); - -// multiple paths - comma -var result = shell.find('resources/find/dir1', 'resources/find/dir2'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); -assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); -assert.equal(result.length, 6); - -// multiple paths - array -var result = shell.find(['resources/find/dir1', 'resources/find/dir2']); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); -assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); -assert.equal(result.length, 6); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/grep.js b/enyo/tools/node_modules/shelljs/test/grep.js deleted file mode 100644 index 498d353..0000000 --- a/enyo/tools/node_modules/shelljs/test/grep.js +++ /dev/null @@ -1,59 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.grep(); -assert.ok(shell.error()); - -shell.grep(/asdf/g); // too few args -assert.ok(shell.error()); - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -shell.grep(/asdf/g, '/asdfasdf'); // no such file -assert.ok(shell.error()); - -// -// Valids -// - -var result = shell.grep('line', 'resources/a.txt'); -assert.equal(shell.error(), null); -assert.equal(result.split('\n').length - 1, 4); - -var result = shell.grep('-v', 'line', 'resources/a.txt'); -assert.equal(shell.error(), null); -assert.equal(result.split('\n').length - 1, 8); - -var result = shell.grep('line one', 'resources/a.txt'); -assert.equal(shell.error(), null); -assert.equal(result, 'This is line one\n'); - -// multiple files -var result = shell.grep(/test/, 'resources/file1.txt', 'resources/file2.txt'); -assert.equal(shell.error(), null); -assert.equal(result, 'test1\ntest2\n'); - -// multiple files, array syntax -var result = shell.grep(/test/, ['resources/file1.txt', 'resources/file2.txt']); -assert.equal(shell.error(), null); -assert.equal(result, 'test1\ntest2\n'); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/ls.js b/enyo/tools/node_modules/shelljs/test/ls.js deleted file mode 100644 index c826323..0000000 --- a/enyo/tools/node_modules/shelljs/test/ls.js +++ /dev/null @@ -1,202 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -var result = shell.ls('/asdfasdf'); // no such file or dir -assert.ok(shell.error()); -assert.equal(result.length, 0); - -// -// Valids -// - -var result = shell.ls(); -assert.equal(shell.error(), null); - -var result = shell.ls('/'); -assert.equal(shell.error(), null); - -// no args -shell.cd('resources/ls'); -var result = shell.ls(); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('file1') > -1, true); -assert.equal(result.indexOf('file2') > -1, true); -assert.equal(result.indexOf('file1.js') > -1, true); -assert.equal(result.indexOf('file2.js') > -1, true); -assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.length, 6); -shell.cd('../..'); - -// simple arg -var result = shell.ls('resources/ls'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('file1') > -1, true); -assert.equal(result.indexOf('file2') > -1, true); -assert.equal(result.indexOf('file1.js') > -1, true); -assert.equal(result.indexOf('file2.js') > -1, true); -assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.length, 6); - -// no args, 'all' option -shell.cd('resources/ls'); -var result = shell.ls('-A'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('file1') > -1, true); -assert.equal(result.indexOf('file2') > -1, true); -assert.equal(result.indexOf('file1.js') > -1, true); -assert.equal(result.indexOf('file2.js') > -1, true); -assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.indexOf('.hidden_file') > -1, true); -assert.equal(result.indexOf('.hidden_dir') > -1, true); -assert.equal(result.length, 8); -shell.cd('../..'); - -// no args, 'all' option -shell.cd('resources/ls'); -var result = shell.ls('-a'); // (deprecated) backwards compatibility test -assert.equal(shell.error(), null); -assert.equal(result.indexOf('file1') > -1, true); -assert.equal(result.indexOf('file2') > -1, true); -assert.equal(result.indexOf('file1.js') > -1, true); -assert.equal(result.indexOf('file2.js') > -1, true); -assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.indexOf('.hidden_file') > -1, true); -assert.equal(result.indexOf('.hidden_dir') > -1, true); -assert.equal(result.length, 8); -shell.cd('../..'); - -// wildcard, simple -var result = shell.ls('resources/ls/*'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/ls/file1') > -1, true); -assert.equal(result.indexOf('resources/ls/file2') > -1, true); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); -assert.equal(result.length, 6); - -// wildcard, hidden only -var result = shell.ls('resources/ls/.*'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/ls/.hidden_file') > -1, true); -assert.equal(result.indexOf('resources/ls/.hidden_dir') > -1, true); -assert.equal(result.length, 2); - -// wildcard, mid-file -var result = shell.ls('resources/ls/f*le*'); -assert.equal(shell.error(), null); -assert.equal(result.length, 5); -assert.equal(result.indexOf('resources/ls/file1') > -1, true); -assert.equal(result.indexOf('resources/ls/file2') > -1, true); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); - -// wildcard, mid-file with dot (should escape dot for regex) -var result = shell.ls('resources/ls/f*le*.js'); -assert.equal(shell.error(), null); -assert.equal(result.length, 2); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); - -// wildcard, should not do partial matches -var result = shell.ls('resources/ls/*.j'); // shouldn't get .js -assert.equal(shell.error(), null); -assert.equal(result.length, 0); - -// wildcard, all files with extension -var result = shell.ls('resources/ls/*.*'); -assert.equal(shell.error(), null); -assert.equal(result.length, 3); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); - -// wildcard, with additional path -var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir'); -assert.equal(shell.error(), null); -assert.equal(result.length, 4); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('b_dir') > -1, true); // no wildcard == no path prefix -assert.equal(result.indexOf('nada') > -1, true); // no wildcard == no path prefix - -// wildcard for both paths -var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir/*'); -assert.equal(shell.error(), null); -assert.equal(result.length, 4); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); - -// wildcard for both paths, array -var result = shell.ls(['resources/ls/f*le*.js', 'resources/ls/a_dir/*']); -assert.equal(shell.error(), null); -assert.equal(result.length, 4); -assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); -assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); - -// recursive, no path -shell.cd('resources/ls'); -var result = shell.ls('-R'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); -assert.equal(result.length, 9); -shell.cd('../..'); - -// recusive, path given -var result = shell.ls('-R', 'resources/ls'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); -assert.equal(result.length, 9); - -// recusive, path given - 'all' flag -var result = shell.ls('-RA', 'resources/ls'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('a_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); -assert.equal(result.indexOf('a_dir/.hidden_dir/nada') > -1, true); -assert.equal(result.length, 14); - -// recursive, wildcard -var result = shell.ls('-R', 'resources/ls/*'); -assert.equal(shell.error(), null); -assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); -assert.equal(result.indexOf('resources/ls/a_dir/b_dir/z') > -1, true); -assert.equal(result.length, 9); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/mkdir.js b/enyo/tools/node_modules/shelljs/test/mkdir.js deleted file mode 100644 index 2bc2a0a..0000000 --- a/enyo/tools/node_modules/shelljs/test/mkdir.js +++ /dev/null @@ -1,79 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.mkdir(); -assert.ok(shell.error()); - -var mtime = fs.statSync('tmp').mtime.toString(); -shell.mkdir('tmp'); // dir already exists -assert.ok(shell.error()); -assert.equal(fs.statSync('tmp').mtime.toString(), mtime); // didn't mess with dir - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -shell.mkdir('/asdfasdf/asdfasdf'); // root path does not exist -assert.ok(shell.error()); -assert.equal(fs.existsSync('/asdfasdf'), false); - -// -// Valids -// - -assert.equal(fs.existsSync('tmp/t1'), false); -shell.mkdir('tmp/t1'); // simple dir -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/t1'), true); - -assert.equal(fs.existsSync('tmp/t2'), false); -assert.equal(fs.existsSync('tmp/t3'), false); -shell.mkdir('tmp/t2', 'tmp/t3'); // multiple dirs -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/t2'), true); -assert.equal(fs.existsSync('tmp/t3'), true); - -assert.equal(fs.existsSync('tmp/t1'), true); -assert.equal(fs.existsSync('tmp/t4'), false); -shell.mkdir('tmp/t1', 'tmp/t4'); // one dir exists, one doesn't -assert.equal(numLines(shell.error()), 1); -assert.equal(fs.existsSync('tmp/t1'), true); -assert.equal(fs.existsSync('tmp/t4'), true); - -assert.equal(fs.existsSync('tmp/a'), false); -shell.mkdir('-p', 'tmp/a/b/c'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -shell.rm('-Rf', 'tmp/a'); // revert - -// multiple dirs -shell.mkdir('-p', 'tmp/zzza', 'tmp/zzzb', 'tmp/zzzc'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/zzza'), true); -assert.equal(fs.existsSync('tmp/zzzb'), true); -assert.equal(fs.existsSync('tmp/zzzc'), true); - -// multiple dirs, array syntax -shell.mkdir('-p', ['tmp/yyya', 'tmp/yyyb', 'tmp/yyyc']); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/yyya'), true); -assert.equal(fs.existsSync('tmp/yyyb'), true); -assert.equal(fs.existsSync('tmp/yyyc'), true); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/mv.js b/enyo/tools/node_modules/shelljs/test/mv.js deleted file mode 100644 index fd49d33..0000000 --- a/enyo/tools/node_modules/shelljs/test/mv.js +++ /dev/null @@ -1,130 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// Prepare tmp/ -shell.cp('resources/*', 'tmp'); - -// -// Invalids -// - -shell.mv(); -assert.ok(shell.error()); - -shell.mv('file1'); -assert.ok(shell.error()); - -shell.mv('-f'); -assert.ok(shell.error()); - -shell.mv('-Z', 'tmp/file1', 'tmp/file1'); // option not supported -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/file1'), true); - -shell.mv('asdfasdf', 'tmp'); // source does not exist -assert.ok(shell.error()); -assert.equal(numLines(shell.error()), 1); -assert.equal(fs.existsSync('tmp/asdfasdf'), false); - -shell.mv('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist -assert.ok(shell.error()); -assert.equal(numLines(shell.error()), 2); -assert.equal(fs.existsSync('tmp/asdfasdf1'), false); -assert.equal(fs.existsSync('tmp/asdfasdf2'), false); - -shell.mv('asdfasdf1', 'asdfasdf2', 'tmp/file1'); // too many sources (dest is file) -assert.ok(shell.error()); - -shell.mv('tmp/file1', 'tmp/file2'); // dest already exists -assert.ok(shell.error()); - -shell.mv('tmp/file1', 'tmp/file2', 'tmp/a_file'); // too many sources (exist, but dest is file) -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/a_file'), false); - -shell.mv('tmp/file*', 'tmp/file1'); // can't use wildcard when dest is file -assert.ok(shell.error()); -assert.equal(fs.existsSync('tmp/file1'), true); -assert.equal(fs.existsSync('tmp/file2'), true); -assert.equal(fs.existsSync('tmp/file1.js'), true); -assert.equal(fs.existsSync('tmp/file2.js'), true); - -// -// Valids -// - -shell.cd('tmp'); - -// handles self OK -shell.mkdir('tmp2'); -shell.mv('*', 'tmp2'); // has to handle self (tmp2 --> tmp2) without throwing error -assert.ok(shell.error()); // there's an error, but not fatal -assert.equal(fs.existsSync('tmp2/file1'), true); // moved OK -shell.mv('tmp2/*', '.'); // revert -assert.equal(fs.existsSync('file1'), true); // moved OK - -shell.mv('file1', 'file3'); // one source -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), false); -assert.equal(fs.existsSync('file3'), true); -shell.mv('file3', 'file1'); // revert -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), true); - -// two sources -shell.rm('-rf', 't'); -shell.mkdir('-p', 't'); -shell.mv('file1', 'file2', 't'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), false); -assert.equal(fs.existsSync('file2'), false); -assert.equal(fs.existsSync('t/file1'), true); -assert.equal(fs.existsSync('t/file2'), true); -shell.mv('t/*', '.'); // revert -assert.equal(fs.existsSync('file1'), true); -assert.equal(fs.existsSync('file2'), true); - -// two sources, array style -shell.rm('-rf', 't'); -shell.mkdir('-p', 't'); -shell.mv(['file1', 'file2'], 't'); // two sources -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), false); -assert.equal(fs.existsSync('file2'), false); -assert.equal(fs.existsSync('t/file1'), true); -assert.equal(fs.existsSync('t/file2'), true); -shell.mv('t/*', '.'); // revert -assert.equal(fs.existsSync('file1'), true); -assert.equal(fs.existsSync('file2'), true); - -shell.mv('file*.js', 't'); // wildcard -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1.js'), false); -assert.equal(fs.existsSync('file2.js'), false); -assert.equal(fs.existsSync('t/file1.js'), true); -assert.equal(fs.existsSync('t/file2.js'), true); -shell.mv('t/*', '.'); // revert -assert.equal(fs.existsSync('file1.js'), true); -assert.equal(fs.existsSync('file2.js'), true); - -shell.mv('-f', 'file1', 'file2'); // dest exists, but -f given -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('file1'), false); -assert.equal(fs.existsSync('file2'), true); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/pwd.js b/enyo/tools/node_modules/shelljs/test/pwd.js deleted file mode 100644 index dd4d75c..0000000 --- a/enyo/tools/node_modules/shelljs/test/pwd.js +++ /dev/null @@ -1,28 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'); - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Valids -// - -var _pwd = shell.pwd(); -assert.equal(shell.error(), null); -assert.equal(_pwd, path.resolve('.')); - -shell.cd('tmp'); -var _pwd = shell.pwd(); -assert.equal(shell.error(), null); -assert.equal(path.basename(_pwd), 'tmp'); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/resources/a.txt b/enyo/tools/node_modules/shelljs/test/resources/a.txt deleted file mode 100644 index 356ce49..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/a.txt +++ /dev/null @@ -1,11 +0,0 @@ -This is line one -This is line two - -This is line four -. -. -More content here -. -. - -This is line eleven diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/a b/enyo/tools/node_modules/shelljs/test/resources/cp/a deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/cp/a +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/b b/enyo/tools/node_modules/shelljs/test/resources/cp/b deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/cp/b +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_a/z +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z b/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js b/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js deleted file mode 100644 index 3b2d24a..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/external/node_script.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('node_script_1234'); - diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/tmp/output b/enyo/tools/node_modules/shelljs/test/resources/external/tmp/output deleted file mode 100644 index e69de29..0000000 diff --git a/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js b/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js deleted file mode 100644 index a77652f..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/external/tmp/tempscript.js +++ /dev/null @@ -1 +0,0 @@ -throw __dirname; require('../../global.js'); silent(false); exec('node -e "console.log(1234);"', {silent:false}) \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1 b/enyo/tools/node_modules/shelljs/test/resources/file1 deleted file mode 100644 index f079749..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file1 +++ /dev/null @@ -1 +0,0 @@ -test1 \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1.js b/enyo/tools/node_modules/shelljs/test/resources/file1.js deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file1.js +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/file1.txt b/enyo/tools/node_modules/shelljs/test/resources/file1.txt deleted file mode 100644 index a5bce3f..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file1.txt +++ /dev/null @@ -1 +0,0 @@ -test1 diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2 b/enyo/tools/node_modules/shelljs/test/resources/file2 deleted file mode 100644 index d606037..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file2 +++ /dev/null @@ -1 +0,0 @@ -test2 \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2.js b/enyo/tools/node_modules/shelljs/test/resources/file2.js deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file2.js +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/file2.txt b/enyo/tools/node_modules/shelljs/test/resources/file2.txt deleted file mode 100644 index 180cf83..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/file2.txt +++ /dev/null @@ -1 +0,0 @@ -test2 diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/.hidden b/enyo/tools/node_modules/shelljs/test/resources/find/.hidden deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/.hidden +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/a b/enyo/tools/node_modules/shelljs/test/resources/find/a deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/a +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/b b/enyo/tools/node_modules/shelljs/test/resources/find/b deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/b +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/a_dir1 +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 b/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 b/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/find/dir2/a_dir1 +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_dir/nada +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file b/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/.hidden_file +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada deleted file mode 100644 index 5fedf57..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada +++ /dev/null @@ -1 +0,0 @@ -nada \ No newline at end of file diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada b/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/a_dir/nada +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file1 b/enyo/tools/node_modules/shelljs/test/resources/ls/file1 deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/file1 +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js b/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/file1.js +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file2 b/enyo/tools/node_modules/shelljs/test/resources/ls/file2 deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/file2 +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js b/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js deleted file mode 100644 index 9daeafb..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/file2.js +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped b/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped deleted file mode 100644 index 8bd6648..0000000 --- a/enyo/tools/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped +++ /dev/null @@ -1 +0,0 @@ -asdf diff --git a/enyo/tools/node_modules/shelljs/test/rm.js b/enyo/tools/node_modules/shelljs/test/rm.js deleted file mode 100644 index 732950c..0000000 --- a/enyo/tools/node_modules/shelljs/test/rm.js +++ /dev/null @@ -1,183 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp'); - -// -// Invalids -// - -shell.rm(); -assert.ok(shell.error()); - -shell.rm('asdfasdf'); // file does not exist -assert.ok(shell.error()); - -shell.rm('-f'); // no file -assert.ok(shell.error()); - -shell.rm('-@', 'resources/file1'); // invalid option -assert.ok(shell.error()); -assert.equal(fs.existsSync('resources/file1'), true); - -// -// Valids -// - -// file does not exist, but -f specified -shell.rm('-f', 'asdfasdf'); -assert.equal(shell.error(), null); - - // simple rm - shell.cp('-f', 'resources/file1', 'tmp/file1'); -assert.equal(fs.existsSync('tmp/file1'), true); -shell.rm('tmp/file1'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), false); - -// recursive dir removal - small-caps '-r' -shell.mkdir('-p', 'tmp/a/b/c'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -shell.rm('-rf', 'tmp/a'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/a'), false); - -// recursive dir removal - capital '-R' -shell.mkdir('-p', 'tmp/a/b/c'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -shell.rm('-Rf', 'tmp/a'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/a'), false); - -// recursive dir removal - absolute path -shell.mkdir('-p', 'tmp/a/b/c'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -shell.rm('-Rf', path.resolve('./tmp/a')); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/a'), false); - -// wildcard -shell.cp('-f', 'resources/file*', 'tmp'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), true); -assert.equal(fs.existsSync('tmp/file2'), true); -assert.equal(fs.existsSync('tmp/file1.js'), true); -assert.equal(fs.existsSync('tmp/file2.js'), true); -shell.rm('tmp/file*'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync('tmp/file1'), false); -assert.equal(fs.existsSync('tmp/file2'), false); -assert.equal(fs.existsSync('tmp/file1.js'), false); -assert.equal(fs.existsSync('tmp/file2.js'), false); - -// recursive dir removal -shell.mkdir('-p', 'tmp/a/b/c'); -shell.mkdir('-p', 'tmp/b'); -shell.mkdir('-p', 'tmp/c'); -shell.mkdir('-p', 'tmp/.hidden'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -assert.equal(fs.existsSync('tmp/b'), true); -assert.equal(fs.existsSync('tmp/c'), true); -assert.equal(fs.existsSync('tmp/.hidden'), true); -shell.rm('-rf', 'tmp/*'); -assert.equal(shell.error(), null); -var contents = fs.readdirSync('tmp'); -assert.equal(contents.length, 1); -assert.equal(contents[0], '.hidden'); // shouldn't remove hiddden if no .* given - -// recursive dir removal -shell.mkdir('-p', 'tmp/a/b/c'); -shell.mkdir('-p', 'tmp/b'); -shell.mkdir('-p', 'tmp/c'); -shell.mkdir('-p', 'tmp/.hidden'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -assert.equal(fs.existsSync('tmp/b'), true); -assert.equal(fs.existsSync('tmp/c'), true); -assert.equal(fs.existsSync('tmp/.hidden'), true); -shell.rm('-rf', 'tmp/*', 'tmp/.*'); -assert.equal(shell.error(), null); -var contents = fs.readdirSync('tmp'); -assert.equal(contents.length, 0); - -// recursive dir removal - array-syntax -shell.mkdir('-p', 'tmp/a/b/c'); -shell.mkdir('-p', 'tmp/b'); -shell.mkdir('-p', 'tmp/c'); -shell.mkdir('-p', 'tmp/.hidden'); -assert.equal(fs.existsSync('tmp/a/b/c'), true); -assert.equal(fs.existsSync('tmp/b'), true); -assert.equal(fs.existsSync('tmp/c'), true); -assert.equal(fs.existsSync('tmp/.hidden'), true); -shell.rm('-rf', ['tmp/*', 'tmp/.*']); -assert.equal(shell.error(), null); -var contents = fs.readdirSync('tmp'); -assert.equal(contents.length, 0); - -// removal of a read-only file (unforced) -shell.mkdir('-p', 'tmp/readonly'); -'asdf'.to('tmp/readonly/file1'); -fs.chmodSync('tmp/readonly/file1', '0444'); // -r--r--r-- -shell.rm('tmp/readonly/file1'); -assert.equal(fs.existsSync('tmp/readonly/file1'), true); // bash's rm always asks before removing read-only files - // here we just assume "no" - -// removal of a read-only file (forced) -shell.mkdir('-p', 'tmp/readonly'); -'asdf'.to('tmp/readonly/file2'); -fs.chmodSync('tmp/readonly/file2', '0444'); // -r--r--r-- -shell.rm('-f', 'tmp/readonly/file2'); -assert.equal(fs.existsSync('tmp/readonly/file2'), false); - -// removal of a tree containing read-only files (unforced) -shell.mkdir('-p', 'tmp/tree2'); -'asdf'.to('tmp/tree2/file1'); -'asdf'.to('tmp/tree2/file2'); -fs.chmodSync('tmp/tree2/file1', '0444'); // -r--r--r-- -shell.rm('-r', 'tmp/tree2'); -assert.equal(fs.existsSync('tmp/tree2/file1'), true); -assert.equal(fs.existsSync('tmp/tree2/file2'), false); - -// removal of a tree containing read-only files (forced) -shell.mkdir('-p', 'tmp/tree'); -'asdf'.to('tmp/tree/file1'); -'asdf'.to('tmp/tree/file2'); -fs.chmodSync('tmp/tree/file1', '0444'); // -r--r--r-- -shell.rm('-rf', 'tmp/tree'); -assert.equal(fs.existsSync('tmp/tree'), false); - -// removal of a sub-tree containing read-only and hidden files - rm('dir/*') -shell.mkdir('-p', 'tmp/tree3'); -shell.mkdir('-p', 'tmp/tree3/subtree'); -shell.mkdir('-p', 'tmp/tree3/.hidden'); -'asdf'.to('tmp/tree3/subtree/file'); -'asdf'.to('tmp/tree3/.hidden/file'); -'asdf'.to('tmp/tree3/file'); -fs.chmodSync('tmp/tree3/file', '0444'); // -r--r--r-- -fs.chmodSync('tmp/tree3/subtree/file', '0444'); // -r--r--r-- -fs.chmodSync('tmp/tree3/.hidden/file', '0444'); // -r--r--r-- -shell.rm('-rf', 'tmp/tree3/*', 'tmp/tree3/.*'); // erase dir contents -assert.equal(shell.ls('tmp/tree3').length, 0); - -// removal of a sub-tree containing read-only and hidden files - rm('dir') -shell.mkdir('-p', 'tmp/tree4'); -shell.mkdir('-p', 'tmp/tree4/subtree'); -shell.mkdir('-p', 'tmp/tree4/.hidden'); -'asdf'.to('tmp/tree4/subtree/file'); -'asdf'.to('tmp/tree4/.hidden/file'); -'asdf'.to('tmp/tree4/file'); -fs.chmodSync('tmp/tree4/file', '0444'); // -r--r--r-- -fs.chmodSync('tmp/tree4/subtree/file', '0444'); // -r--r--r-- -fs.chmodSync('tmp/tree4/.hidden/file', '0444'); // -r--r--r-- -shell.rm('-rf', 'tmp/tree4'); // erase dir contents -assert.equal(fs.existsSync('tmp/tree4'), false); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/sed.js b/enyo/tools/node_modules/shelljs/test/sed.js deleted file mode 100644 index d919cb4..0000000 --- a/enyo/tools/node_modules/shelljs/test/sed.js +++ /dev/null @@ -1,58 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.sed(); -assert.ok(shell.error()); - -shell.sed(/asdf/g); // too few args -assert.ok(shell.error()); - -shell.sed(/asdf/g, 'nada'); // too few args -assert.ok(shell.error()); - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -shell.sed(/asdf/g, 'nada', '/asdfasdf'); // no such file -assert.ok(shell.error()); - -// -// Valids -// - -shell.cp('-f', 'resources/file1', 'tmp/file1') -var result = shell.sed('test1', 'hello', 'tmp/file1'); // search string -assert.equal(shell.error(), null); -assert.equal(result, 'hello'); - -var result = shell.sed(/test1/, 'hello', 'tmp/file1'); // search regex -assert.equal(shell.error(), null); -assert.equal(result, 'hello'); - -var result = shell.sed(/test1/, 1234, 'tmp/file1'); // numeric replacement -assert.equal(shell.error(), null); -assert.equal(result, '1234'); - -var result = shell.sed('-i', /test1/, 'hello', 'tmp/file1'); -assert.equal(shell.error(), null); -assert.equal(result, 'hello'); -assert.equal(shell.cat('tmp/file1'), 'hello'); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/silent.js b/enyo/tools/node_modules/shelljs/test/silent.js deleted file mode 100644 index 7da94ab..0000000 --- a/enyo/tools/node_modules/shelljs/test/silent.js +++ /dev/null @@ -1,26 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -// -// Valids -// - -assert.equal(shell.silent(), false); // default - -shell.silent(true); -assert.equal(shell.silent(), true); - -shell.silent(false); -assert.equal(shell.silent(), false); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/tempdir.js b/enyo/tools/node_modules/shelljs/test/tempdir.js deleted file mode 100644 index 63448da..0000000 --- a/enyo/tools/node_modules/shelljs/test/tempdir.js +++ /dev/null @@ -1,27 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Valids -// - -var tmp = shell.tempdir(); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync(tmp), true); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/test.js b/enyo/tools/node_modules/shelljs/test/test.js deleted file mode 100644 index f074c8a..0000000 --- a/enyo/tools/node_modules/shelljs/test/test.js +++ /dev/null @@ -1,83 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -var result = shell.test(); // no expression given -assert.ok(shell.error()); - -var result = shell.test('asdf'); // bad expression -assert.ok(shell.error()); - -var result = shell.test('f', 'resources/file1'); // bad expression -assert.ok(shell.error()); - -var result = shell.test('-f'); // no file -assert.ok(shell.error()); - -// -// Valids -// - -//exists -var result = shell.test('-e', 'resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, true);//true - -var result = shell.test('-e', 'resources/404'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -//directory -var result = shell.test('-d', 'resources'); -assert.equal(shell.error(), null); -assert.equal(result, true);//true - -var result = shell.test('-f', 'resources'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -var result = shell.test('-L', 'resources'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -//file -var result = shell.test('-d', 'resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -var result = shell.test('-f', 'resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, true);//true - -var result = shell.test('-L', 'resources/file1'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -//link -var result = shell.test('-d', 'resources/link'); -assert.equal(shell.error(), null); -assert.equal(result, false); - -var result = shell.test('-f', 'resources/link'); -assert.equal(shell.error(), null); -assert.equal(result, true);//true - -var result = shell.test('-L', 'resources/link'); -assert.equal(shell.error(), null); -assert.equal(result, true);//true - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/to.js b/enyo/tools/node_modules/shelljs/test/to.js deleted file mode 100644 index 4ce9893..0000000 --- a/enyo/tools/node_modules/shelljs/test/to.js +++ /dev/null @@ -1,39 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -'hello world'.to(); -assert.ok(shell.error()); - -assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check -'hello world'.to('/asdfasdf/file'); -assert.ok(shell.error()); - -// -// Valids -// - -'hello world'.to('tmp/to1'); -var result = shell.cat('tmp/to1'); -assert.equal(shell.error(), null); -assert.equal(result, 'hello world'); - -shell.exit(123); diff --git a/enyo/tools/node_modules/shelljs/test/which.js b/enyo/tools/node_modules/shelljs/test/which.js deleted file mode 100644 index b733cb6..0000000 --- a/enyo/tools/node_modules/shelljs/test/which.js +++ /dev/null @@ -1,38 +0,0 @@ -var shell = require('..'); - -var assert = require('assert'), - path = require('path'), - fs = require('fs'); - -// Node shims for < v0.7 -fs.existsSync = fs.existsSync || path.existsSync; - -shell.silent(true); - -function numLines(str) { - return typeof str === 'string' ? str.match(/\n/g).length : 0; -} - -shell.rm('-rf', 'tmp'); -shell.mkdir('tmp') - -// -// Invalids -// - -shell.which(); -assert.ok(shell.error()); - -var result = shell.which('asdfasdfasdfasdfasdf'); // what are the odds... -assert.equal(shell.error(), null); -assert.equal(result, null); - -// -// Valids -// - -var result = shell.which('node'); -assert.equal(shell.error(), null); -assert.equal(fs.existsSync(result), true); - -shell.exit(123); diff --git a/enyo/tools/test/ajax/index.html b/enyo/tools/test/ajax/index.html deleted file mode 100644 index 8020cd9..0000000 --- a/enyo/tools/test/ajax/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/enyo/tools/test/ajax/package.js b/enyo/tools/test/ajax/package.js deleted file mode 100644 index 1dde9a3..0000000 --- a/enyo/tools/test/ajax/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "$lib/extra/test" -); diff --git a/enyo/tools/test/ajax/php/redball.jpg b/enyo/tools/test/ajax/php/redball.jpg deleted file mode 100644 index c836adca6be5af12c1002b24d432067d3e4cce35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmex=hUwp4U!^w!2dQ|0V!zR8`IZ diff --git a/enyo/tools/test/ajax/php/test1.php b/enyo/tools/test/ajax/php/test1.php deleted file mode 100644 index ab54aa8..0000000 --- a/enyo/tools/test/ajax/php/test1.php +++ /dev/null @@ -1,18 +0,0 @@ -' . "\n"; - echo "hello"; -} elseif ($format == 'jsonp') { - header('Content-Type: text/javascript'); - echo "$callback("; - echo json_encode(array('response' => 'hello', 'utf8' => 'Ви́хри')); - echo ');'; -} else { - echo json_encode(array('response' => 'hello')); -} -?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test2.php b/enyo/tools/test/ajax/php/test2.php deleted file mode 100644 index 3bc83e6..0000000 --- a/enyo/tools/test/ajax/php/test2.php +++ /dev/null @@ -1,54 +0,0 @@ - "get"); - echo json_encode($result); -} - -function post() { - $q = @$_POST['query']; - if ($q) { - $result = array('response' => "post.".$q); - } else { - $q = @$_GET['query']; - if ($q) { - $result = array('response' => "query.".$q); - }else{ - $result = array('response' => file_get_contents('php://input')); - } - } - $requested_with = @$_SERVER['HTTP_X_REQUESTED_WITH']; - if ($requested_with == 'XMLHttpRequest') { - $result['isAjax'] = true; - } - echo json_encode($result); -} - -function put() { - $c = @$_SERVER["CONTENT_TYPE"]; - $result = array('status' => "put", 'ctype' => $c); - echo json_encode($result); -} - -function delete() { - $result = array('status' => "delete"); - echo json_encode($result); -} -?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test3.php b/enyo/tools/test/ajax/php/test3.php deleted file mode 100644 index 6e8ab20..0000000 --- a/enyo/tools/test/ajax/php/test3.php +++ /dev/null @@ -1,15 +0,0 @@ - "get"); - echo json_encode($result); -} diff --git a/enyo/tools/test/ajax/php/test4.php b/enyo/tools/test/ajax/php/test4.php deleted file mode 100644 index 0a70096..0000000 --- a/enyo/tools/test/ajax/php/test4.php +++ /dev/null @@ -1,22 +0,0 @@ - "post" , 'ctype' => $ctype , 'cacheCtrl' => $cacheCtrl); - echo json_encode($result); - - # useful for test setup... - #foreach ($_SERVER as $name => $value) { - # echo "$name: $value\n"; - #} -} -?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test5.php b/enyo/tools/test/ajax/php/test5.php deleted file mode 100644 index cddb60a..0000000 --- a/enyo/tools/test/ajax/php/test5.php +++ /dev/null @@ -1,20 +0,0 @@ -header('HTTP/1.1 500: Internal Server Error'); - //header('HTTP/1.1 500 Internal Server Error'); - //http_response_code(500); // php >= 5.4 - header('X-PHP-Response-Code: 500', true, 500); // php >= 4.3 - - // can't use odd charset due to IE exception throwing - //header('Content-Type: text/plain; charset=x-user-unparseable'); - header('Content-Type: text/plain; charset=utf-8'); - - echo "my error description"; - break; - default: - echo "invalid method"; -} -?> \ No newline at end of file diff --git a/enyo/tools/test/ajax/php/test6.php b/enyo/tools/test/ajax/php/test6.php deleted file mode 100644 index 8c7b124..0000000 --- a/enyo/tools/test/ajax/php/test6.php +++ /dev/null @@ -1,31 +0,0 @@ - "get"); - echo json_encode($result); - - # $attachment_location = $_SERVER["DOCUMENT_ROOT"] . "/file.zip"; - $attachment_location = "redball.jpg"; - if (file_exists($attachment_location)) { - - header($_SERVER["SERVER_PROTOCOL"] . " 200 OK"); - header("Cache-Control: public"); // needed for i.e. - header("Content-Type: image/jpeg"); - header("Content-Transfer-Encoding: Binary"); - header("Content-Length:".filesize($attachment_location)); - header("Content-Disposition: attachment; filename=redball.jpg"); - readfile($attachment_location); - die(); - } else { - die("Error: File not found."); - } -} diff --git a/enyo/tools/test/ajax/tests/AjaxTest.js b/enyo/tools/test/ajax/tests/AjaxTest.js deleted file mode 100644 index 3f39596..0000000 --- a/enyo/tools/test/ajax/tests/AjaxTest.js +++ /dev/null @@ -1,246 +0,0 @@ -enyo.kind({ - name: "AjaxTest", - kind: enyo.TestSuite, - timeout: 10000, - testContextSuccess: function (){ - var self = this, - context = {testStatus: 'success'}; - return new enyo.Ajax({url: "php/test1.php?format=test"}) - .response(context, function(inSender, inValue) { - if (this.testStatus && this.testStatus === 'success') { - self.finish(""); - } else { - self.finish("response context not correctly bound"); - } - }) - .error(context, function(inSender, inError) { - self.finish("simple request failed"); - }) - .go(); - }, - testContextFailure: function (){ - var self = this, - context = {testStatus: 'success'}; - return new enyo.Ajax({url: "php/nowhere.php"}) - .response(context, function(inSender, inValue) { - self.finish("simple request failed"); - }) - .error(context, function(inSender, inError) { - if (this.testStatus && this.testStatus === 'success') { - self.finish(""); - } else { - self.finish("failure context not correctly bound"); - } - }) - .go(); - }, - _testAjax: function(inProps, inParams, inAssertFn, inAssertErrFn) { - return new enyo.Ajax(inProps) - .response(this, function(inSender, inValue) { - this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue)); - }) - .error(this, function(inSender, inError) { - if (!inAssertErrFn) { - this.finish("bad status: " + inError.toString()); - enyo.error(inError); - enyo.error(inError.stack); - } else { - this.finish(inAssertErrFn.call(null, inError) ? "" : "bad response: " + inError); - } - }) - .go(inParams); - }, - _testResponse: function(inProps, inAssertFn) { - this._testAjax(enyo.mixin({url: "php/test1.php?format=" + inProps.handleAs}, inProps), null, inAssertFn); - }, - testJsonResponse: function() { - this._testResponse({handleAs: "json"}, function(inValue) { - return inValue.response == "hello"; - }); - }, - testTextResponse: function() { - this._testResponse({handleAs: "text"}, function(inValue) { - return inValue == "hello"; - }); - }, - testXmlResponse: function() { - this._testResponse({handleAs: "xml"}, function(inValue) { - var r = inValue.getElementsByTagName("response")[0].childNodes[0].nodeValue; - return r == "hello"; - }); - }, - testSyncTextResponse: function() { - this._testResponse({handleAs: "text", sync: true}, function(inValue) { - return inValue == "hello"; - }); - }, - // try a post with query object - testPostRequestQuery: function() { - this._testAjax({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) { - return inValue.response == "query.enyo"; - }); - }, - testPostRequestQueryWithPayload: function() { - this._testAjax({url: "php/test2.php", method: "POST", postBody:"data"}, {query: "enyo"}, function(inValue) { - return inValue.response == "query.enyo"; - }); - }, - testPostRequestPayload: function() { - this._testAjax({url: "php/test2.php", method: "POST", postBody:"query=enyo"}, null, function(inValue) { - return inValue.response == "post.enyo"; - }); - }, - testPutRequest: function() { - this._testAjax({url: "php/test2.php", method: "PUT"}, null, function(inValue) { - return inValue.status == "put"; - }); - }, - testDeleteRequest: function() { - this._testAjax({url: "php/test2.php", method: "DELETE"}, null, function(inValue) { - return inValue.status == "delete"; - }); - }, - testHeader: function() { - this._testAjax({url: "php/test2.php", method: "POST", headers: {"X-Requested-With": "XMLHttpRequest"}}, {query: "enyo"}, function(inValue) { - return inValue.isAjax; - }); - }, - testPostBody: function() { - this._testAjax({url: "php/test2.php", method: "POST", postBody: "This is a test."}, null, function(inValue) { - return inValue.response == "This is a test."; - }); - }, - testContentType: function() { - var contentType = "text/plain"; - this._testAjax({url: "php/test2.php", method: "PUT", contentType: contentType}, null, function(inValue) { - return (inValue.ctype === contentType); - }); - }, - testCacheControlOn: function() { - // skip test on non-iOS platforms, since Firefox always sends cache-control header causing - // false positive - if (!enyo.platform.ios) { - this.finish(); - return; - } - var contentType = "application/x-www-form-urlencoded"; - this._testAjax({url: "php/test4.php", method: "POST", postBody: "data"}, null, function(inValue) { - if (enyo.platform.ios && enyo.platform.ios >= 6) { - var status = inValue.cacheCtrl && (inValue.cacheCtrl.indexOf('no-cache') === 0); - if (!status) { - enyo.log("Bad Cache-Control: " + inValue.cacheCtrl + " expected: " + "no-cache"); - } - return status; - } else { - return true; - } - }); - }, - testCacheControlOff: function() { - // skip test on non-iOS platforms, since Firefox always sends cache-control header causing - // false positive - if (!enyo.platform.ios) { - this.finish(); - return; - } - var contentType = "application/x-www-form-urlencoded"; - this._testAjax({url: "php/test4.php", method: "POST", postBody: "data", headers: {'cache-control': null} }, null, function(inValue) { - var status = (inValue.cacheCtrl === null); - if (!status) { - enyo.log("Bad Cache-Control: " + inValue.cacheCtrl + " expected: " + undefined); - } - return status; - }); - }, - testContentTypeDefault: function() { - var contentType = "application/x-www-form-urlencoded"; - this._testAjax({url: "php/test4.php", method: "POST", postBody: "data"}, null, function(inValue) { - var status = (inValue.ctype.indexOf(contentType) === 0); - if (!status) { - enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); - } - return status; - }); - }, - testContentTypeFormDataField: function() { - var formData = new enyo.FormData(); - formData.append('token', "data"); - var contentType = "multipart/form-data"; - this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) { - var status = (inValue.ctype.indexOf(contentType) === 0) && - (inValue.ctype.indexOf("boundary=--") > 10); - if (!status) { - enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); - } - return status; - }); - }, - testContentTypeFormDataFile: function() { - var formData = new enyo.FormData(); - var file = new enyo.Blob(["Some Random File Content!", "And some more..."], { - name: "myFile" - }); - formData.append('file', file); - var contentType = "multipart/form-data"; - this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) { - var status = (inValue.ctype.indexOf(contentType) === 0) && - (inValue.ctype.indexOf("boundary=--") > 10); - if (!status) { - enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType); - } - return status; - }); - }, - testXhrStatus: function() { - var ajax = this._testAjax({url: "php/test2.php"}, null, function(inValue) { - return ajax.xhr.status == 200; - }); - }, - testXhrFields: function() { - var ajax = this._testAjax({url: "php/test2.php", xhrFields: {withCredentials: true}}, null, function(inValue) { - return ajax.xhr.withCredentials; - }); - }, - // test CORS (Cross-Origin Resource Sharing) by testing against youtube api - testCORS: function() { - this._testAjax({url: "http://query.yahooapis.com/v1/public/yql/jonathan/weather/"}, {q:'select * from weather.forecast where location=94025', format: "json"}, function(inValue) { - return inValue && inValue.query && inValue.query.results && inValue.query.count > 0; - }); - }, - // test CORS failure - testCORSFailure: function() { - new enyo.Ajax({url: "https://dev.virtualearth.net/REST/v1/Locations/47.64054,-122.12934"}) - .response(this, function(inSender, inValue) { - this.finish("CORS failure flagged as success"); - }) - .error(this, function(inSender, inValue) { - this.finish(""); - }) - .go(); - }, - // server is set to respond after 3 seconds, so make sure timeout fires first - testAjaxTimeout: function() { - new enyo.Ajax({url: "php/test3.php", timeout: 500}) - .response(this, function(inSender, inValue) { - this.finish("did not timeout"); - }) - .error(this, function(inSender, inValue) { - // extra timeout is to make sure that timeout fail code cancels XHR - enyo.job("timeouttest", enyo.bind(this, function() {this.finish("");}), 4000); - }) - .go(); - }, - // expected to fail - testErrorResponse: function() { - var req = this._testAjax({url: "php/test5.php"}, null, function(inValue) { - // getting success means server sent wrong response - return false; - }, function(inError) { - return (inError === 500) && - req.xhrResponse && - (req.xhrResponse.status === 500) && - (req.xhrResponse.headers['content-type'] === "text/plain; charset=utf-8") && - (req.xhrResponse.body === "my error description"); - }); - } -}); diff --git a/enyo/tools/test/ajax/tests/JsonpTest.js b/enyo/tools/test/ajax/tests/JsonpTest.js deleted file mode 100644 index eeec061..0000000 --- a/enyo/tools/test/ajax/tests/JsonpTest.js +++ /dev/null @@ -1,29 +0,0 @@ -enyo.kind({ - name: "JsonpTest", - kind: enyo.TestSuite, - _testJsonp: function(inProps, inParams, inAssertFn) { - return new enyo.JsonpRequest(inProps) - .response(this, function(inSender, inValue) { - this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue)); - }) - .error(this, function(inSender, inValue) { - this.finish("bad status: " + inValue); - enyo.error(inValue); - }) - .go(inParams); - }, - _testResponse: function(inProps, inAssertFn) { - this._testJsonp(enyo.mixin({url: "php/test1.php?format=jsonp", callbackName: "callback"}, inProps), - null, inAssertFn); - }, - testJsonResponse: function() { - this._testResponse({}, function(inValue) { - return inValue.response == "hello"; - }); - }, - testCharset: function() { - this._testResponse({charset: "utf8"}, function(inValue) { - return inValue.utf8 == "\u0412\u0438\u0301\u0445\u0440\u0438"; - }); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/WebServiceTest.js b/enyo/tools/test/ajax/tests/WebServiceTest.js deleted file mode 100644 index fc1f4ff..0000000 --- a/enyo/tools/test/ajax/tests/WebServiceTest.js +++ /dev/null @@ -1,112 +0,0 @@ -enyo.kind({ - name: "WebServiceTest", - kind: enyo.TestSuite, - timeout: 10000, - _testWebService: function(inProps, inParams, inAssertFn) { - var ws = this.createComponent({kind: enyo.WebService, onResponse: "_response", onError: "_error", assertFn: inAssertFn}, inProps); - return ws.send(inParams); - }, - _response: function(inSender, inValue) { - this.finish(inSender.assertFn(inValue.data) ? "" : "bad response: " + JSON.stringify(inValue.data)); - }, - _error: function(inSender, inValue) { - this.finish("bad status: " + inValue.data); - }, - _testResponse: function(inProps, inAssertFn) { - this._testWebService(enyo.mixin({url: "php/test1.php?format=" + (inProps.format || inProps.handleAs)}, inProps), null, inAssertFn); - }, - testJsonResponse: function() { - this._testResponse({handleAs: "json"}, - function(inValue) { - return inValue.response == "hello"; - } - ); - }, - testTextResponse: function() { - this._testResponse({handleAs: "text"}, function(inValue) { - return inValue == "hello"; - }); - }, - testXmlResponse: function() { - this._testResponse({handleAs: "xml"}, function(inValue) { - var r = inValue.getElementsByTagName("response")[0].childNodes[0].nodeValue; - return r == "hello"; - }); - }, - testPostRequest: function() { - this._testWebService({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) { - return inValue.response == "query.enyo"; - }); - }, - testPutRequest: function() { - this._testWebService({url: "php/test2.php", method: "PUT"}, null, function(inValue) { - return inValue.status == "put"; - }); - }, - testDeleteRequest: function() { - this._testWebService({url: "php/test2.php", method: "DELETE"}, null, function(inValue) { - return inValue.status == "delete"; - }); - }, - testHeader: function() { - this._testWebService({url: "php/test2.php", method: "POST", headers: {"X-Requested-With": "XMLHttpRequest"}}, {query: "enyo"}, function(inValue) { - return inValue.isAjax; - }); - }, - testPostBody: function() { - this._testWebService({url: "php/test2.php", method: "POST", postBody: "This is a test."}, null, function(inValue) { - return inValue.response == "This is a test."; - }); - }, - testContentType: function() { - var contentType = "text/plain"; - this._testWebService({url: "php/test2.php", method: "PUT", contentType: contentType}, null, function(inValue) { - return inValue.ctype == contentType; - }); - }, - testXhrStatus: function() { - var ajax = this._testWebService({url: "php/test2.php"}, null, function(inValue) { - return ajax.xhr.status == 200; - }); - }, - testXhrFields: function() { - var ajax = this._testWebService({url: "php/test2.php", xhrFields: {withCredentials: true}}, null, function(inValue) { - return ajax.xhr.withCredentials; - }); - }, - // test CORS (Cross-Origin Resource Sharing) by testing against youtube api - testCORS: function() { - this._testWebService({ - url: "http://query.yahooapis.com/v1/public/yql/jonathan/weather/"}, - {q: 'select * from weather.forecast where location=94025', format: "json"}, - function(inValue) { - enyo.log(inValue); - return inValue && inValue.query && inValue.query.results && inValue.query.count > 0; - }); - }, - testJsonp: function() { - this._testResponse({jsonp: true, format: "jsonp"}, function(inValue) { - return inValue.response == "hello"; - }); - }, - /*testCharset: function() { - this._testResponse({charset: "utf8"}, function(inValue) { - return inValue.utf8 == "\u0412\u0438\u0301\u0445\u0440\u0438"; - }); - } - */ - // server is set to respond after 3 seconds, so make sure timeout fires first - _timeoutResponse: function(inSender, inEvent) { - this.finish("did not timeout"); - }, - _timeoutError: function(inSender, inEvent) { - // extra timeout is to make sure that timeout fail code cancels XHR - enyo.job("wstimeouttest", enyo.bind(this, function() {this.finish("");}), 4000); - }, - testTimeout: function() { - var ws = this.createComponent({kind: enyo.WebService, - onResponse: "_timeoutResponse", onError: "_timeoutError"}, - {url: "php/test3.php", timeout: 500}); - ws.send(); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/XhrTest.js b/enyo/tools/test/ajax/tests/XhrTest.js deleted file mode 100644 index 6d3ee5f..0000000 --- a/enyo/tools/test/ajax/tests/XhrTest.js +++ /dev/null @@ -1,16 +0,0 @@ -enyo.kind({ - name: "XhrTest", - kind: enyo.TestSuite, - testXhrSync: function() { - var x = enyo.xhr.request({ - url: "php/test1.php?format=text", - sync: true - }); - if (x.responseText) { - this.finish(""); - } - else { - this.finish("sync XHR didn't return with text"); - } - } -}); \ No newline at end of file diff --git a/enyo/tools/test/ajax/tests/package.js b/enyo/tools/test/ajax/tests/package.js deleted file mode 100644 index a16be51..0000000 --- a/enyo/tools/test/ajax/tests/package.js +++ /dev/null @@ -1,6 +0,0 @@ -enyo.depends( - "XhrTest.js", - "AjaxTest.js", - "JsonpTest.js", - "WebServiceTest.js" -); diff --git a/enyo/tools/test/core/index.html b/enyo/tools/test/core/index.html deleted file mode 100644 index 929e707..0000000 --- a/enyo/tools/test/core/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Enyo Core Tests - - - - - - - - - diff --git a/enyo/tools/test/core/test.css b/enyo/tools/test/core/test.css deleted file mode 100644 index 26f0fa7..0000000 --- a/enyo/tools/test/core/test.css +++ /dev/null @@ -1,33 +0,0 @@ -.enyo-testcase { - font-family: Helvetica, Arial, sans-serif; - font-size: smaller; -} - -.enyo-testcase-title { - font-weight: bold; - padding: 4px; - color: white; - background-color: #222; - text-align: center; -} - -.enyo-testcase-group { -} - -.enyo-testcase-running, .enyo-testcase-passed, .enyo-testcase-failed { - padding: 4px 4px 4px 36px; - border-bottom: 1px dotted gray; - white-space: pre; -} - -.enyo-testcase-running { - background-color: yellow; -} - -.enyo-testcase-passed { - background-color: #B0FFB0; -} - -.enyo-testcase-failed { - background-color: #FF8080; -} \ No newline at end of file diff --git a/enyo/tools/test/core/test.js b/enyo/tools/test/core/test.js deleted file mode 100644 index b5f7fb8..0000000 --- a/enyo/tools/test/core/test.js +++ /dev/null @@ -1,303 +0,0 @@ - -// TestRunner.js - -/* -To add a test case: - 1) Create a subclass of EnyoTestCase - 2) Add file to package.js -*/ -enyo.kind({ - name: "enyo.TestRunner", - kind: enyo.Control, - index: 0, - rendered: function() { - this.inherited(arguments); - this.next(); - }, - next: function() { - var test = enyo.TestSuite.tests[this.index++]; - if (test) { - this.createComponent({name: test.prototype.kindName, kind: enyo.TestReporter, onFinishAll: "next"}).render().runTests(); - } - } -}); - -// TestSuite.js - -/*global enyo, console -*/ -/* -Test Package Wish list: ------------------------ -Collapse success results for a suite, so large swaths of green don't hide the red. -Expandable stack trace & logging for failures, so they can be collapsed by default. -Support for async beforeEach & afterEach -Jasmine style assert mechanism, so we can have fancy english text for failures - e.g., this.assert("spreadsheet total", total).equals(15) yields "Expected spreadsheet total 12 to equal 15" - -*/ - - -/** - To implement a suite of unit tests, create a subkind of enyo.TestSuite. - Any methods in your subkind that begin with 'test' will be invoked as unit tests when the test runner executes. - - When each test is complete, it should call this.finish(). - Pass nothing for success, or something truthy for failure (usually an explanatory message or an exception object). - If you do not call finish(), your test will be failed after a 3-second timeout. - This timeout can be customized for a given test by calling this.resetTimeout(ms). - - - See enyo-support/tests for example framework tests. - -*/ -enyo.kind({ - name: "enyo.TestSuite", - kind: enyo.Component, - events: { - onBegin: "", // sent with test name as each test begins running. - onFinish: "", // sent with result as each test completes. - onFinishAll: "" // sent when all tests are finished. - }, - timeout: 3000, - timeoutMessage: "timed out", - /** @public - Replaces the current test timeout with - May be called by individual tests to reset/lengthen/shorten the test timeout. - Mostly good for unusually long-running tests, but can be used for shortening the timeout duration, or - even for setting different timeouts for successive stages of a test. - */ - resetTimeout: function(timeout) { - this.clearTimer(); - this.timer = window.setTimeout(enyo.bind(this, "timedout"), timeout || this.timeout); - }, - /** @public - Tests can call this.log() to print useful diagnostic information. - The logs are accumulated, and only displayed when the test fails. - Logged objects will be automatically converted to JSON. - */ - log: function(msg) { - this.logMessages = this.logMessages || []; - if (typeof msg !== "string") { - msg = JSON.stringify(msg); - } - this.logMessages.push(msg); - }, - // Subclasses can override this method. - // It will be called before each test executes. - // It can be used to run common setup code. - beforeEach: function() { - }, - // Subclasses can override this method. - // It will be called exactly once as each test finishes, even in failure cases. - // It can be used to reliably execute cleanup code. - afterEach: function() { - }, - // Runs all the tests in the suite. - // This component can operate in a couple of modes... one where it runs all tests, and one where it runs only a single test. - // When running all tests, it allocates a fresh child component for each test, and then uses that to do actually run the test, - // passing along any relevant events to our owner. The reason for this is to eliminate unintentional state sharing between tests, - // and to make sure that lingering test code that calls finish() at a later time does not affect the state of a different test. - runAllTests: function() { - if (this.autoRunNextTest) { - console.error("TestSuite.runAllTests: Already running."); - return; // already running. - } - this.testNames = this.getTestNames(); - this.index = 0; - this.autoRunNextTest = true; - this.next(); - }, - getTestNames: function() { - // NOTE: name no function or property test* before this point unless it's really a test - var names = []; - for (var key in this) { - if (/^test/.test(key)) { - names.push(key); - } - } - return names; - }, - next: function() { - var testName; - if (!this.autoRunNextTest) { - return; - } - testName = this.testNames[this.index++]; - this.current = testName; - if (testName) { - // Allocate a new child component to run the test. - if (this.$[testName]) { - this.$[testName].destroy(); - } - this.createComponent({name: testName, kind:this.kind, onBegin: "childTestBegun", onFinish: "childTestFinished"}); - this.$[testName].runTest(testName); - } else { - this.autoRunNextTest = false; - this.doFinishAll(); - } - }, - // Called on a component running in the "run a single test" mode to run the actual test. - runTest: function(inTestName) { - this.resetTimeout(); - this.doBegin({testName: inTestName}); - try { - // actual test code invoked here - this.beforeEach(); - this[inTestName](); - } catch(x) { - this.finish(x); - } - }, - timedout: function() { - this.finish(this.timeoutMessage); - }, - clearTimer: function() { - window.clearTimeout(this.timer); - }, - // Call finish() to indicate success, or finish("") to indicate failure. - finish: function(inMessage) { - enyo.asyncMethod(this, "reallyFinish", inMessage); - }, - reallyFinish: function(inMessage) { - // If finish has been called before, then we ignore it - // unless we passed previously and now we're failing. - // We will send multiple finish events if we get a success and then a failure -- that counts as a failure. - if (this.results) { - console.warn("Finish called more than once in test "+this.name); - if (!this.results.passed || !inMessage) { - return; - } - } - this.results = { - suite: this.kindName, - name: this.name, - passed: !inMessage, - logs: this.logMessages - }; - if (inMessage) { - if ((typeof inMessage) === "string") { // In message could be a string... - this.results.message = inMessage; - } else if (inMessage.message !== undefined) { // ... or an exception ... - this.results.message = inMessage.message; - this.results.exception = inMessage; - } else { // ... or some other object ... - this.results.message = inMessage.errorText || inMessage.toString(); - this.results.failValue = inMessage; - } - // Except for timeouts, make sure we have an exception so we can get a backtrace. - if (!this.results.exception && inMessage !== this.timeoutMessage) { - try { - throw new Error(inMessage); - } catch(e) { - this.results.exception = e; - } - } - } - this.clearTimer(); - // Execute afterEach method, if we haven't already. - if (this.afterEach) { - try { - this.afterEach(); - } catch(x) { - this.afterEach = null; // so we don't try again when we recurse. - this.finish(x); // we count an afterEach exception as a failure, even if the test result was originally success. - } - this.afterEach = null; // so we don't try again - } - this.doFinish({results: this.results}); // bubble results - }, - childTestBegun: function(inSender) { - // Pass child test begin event up, with the test name. - // This can be used to trigger UI. - this.triggeredNextTest = false; - }, - childTestFinished: function(inSender, inResults) { - // We do not destroy the child component yet, in case it calls finish() again later with a failure... in that case, we still fail it. - if (!this.triggeredNextTest) { - this.triggeredNextTest = true; - enyo.asyncMethod(this, "next"); - } - } - -}); - -enyo.TestSuite.tests = []; - -enyo.TestSuite.subclass = function(ctor, props) { - // make a list of TestSuite subclasses so we can run them automatically - // if one needs to make a TestSuite subclass that isn't actually a TestSuite itself, - // they should assign a truthy 'testBase' property - if (!props.testBase) { - enyo.TestSuite.tests.push(ctor); - } -}; - -// TestReporter.js - -// UI kind responsible for creating test component, running tests, receiving & displaying test results. -enyo.kind({ - name: "enyo.TestReporter", - kind: enyo.Control, - published: { - results: null - }, - events: { - onFinishAll: "" - }, - components: [ - {name: "title", classes: "enyo-testcase-title"}, - {name: "group", classes: "enyo-testcase-group"} - ], - classes: "enyo-testcase", - timeout: 3000, - create: function() { - this.inherited(arguments); - this.$.title.setContent(this.name); - }, - initComponents: function() { - this.inherited(arguments); - this.createComponent({name: "testSuite", kind: this.name, onBegin: "testBegun", onFinish: "updateTestDisplay"}); - }, - runTests: function() { - this.$.testSuite.runAllTests(); - }, - testBegun: function(inSender, inEvent) { - this.$.group.createComponent({name: inEvent.testName, classes: "enyo-testcase-running", content: inEvent.testName + ": running", allowHtml: true}).render(); - }, - formatStackTrace: function(inStack) { - var stack = inStack.split("\n"); - var out = ['']; - for (var i=0, s; s=stack[i]; i++) { - if (s.indexOf(" at Object.do") == 0 || s.indexOf(" at Object.dispatch") == 0 || s.indexOf("TestSuite.js") != -1) { - continue; - } - out.push(s); - } - return out.join("
    "); - }, - updateTestDisplay: function(inSender, inEvent) { - var results = inEvent.results; - var e = results.exception; - var info = this.$.group.$[results.name]; - var content = "" + results.name + ": " + (results.passed ? "PASSED" : results.message); - if (e) { - // If we have an exception include the stack trace or file/line number. - if (e.stack) { - content += this.formatStackTrace(e.stack); - } else if (e.sourceURL && e.line) { - content += "
    " + e.sourceURL + ":" + e.line; - } - // if fail was called with an object, show the JSON. This is likely a service request error or somesuch. - if (results.failValue) { - content += "
    " + enyo.json.stringify(results.failValue).replace(/\\n/g, "
    "); - } - } - // Show logs if we have any. - if (!results.passed && results.logs) { - content += "
    " + results.logs.join("
    "); - } - info.setContent(content); - info.setClasses("enyo-testcase-" + (results.passed ? "passed" : "failed")); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/AjaxTest.js b/enyo/tools/test/core/tests/AjaxTest.js deleted file mode 100644 index 9cb43ab..0000000 --- a/enyo/tools/test/core/tests/AjaxTest.js +++ /dev/null @@ -1,53 +0,0 @@ -enyo.kind({ - name: "AjaxTest", - kind: enyo.TestSuite, - testAjax200: function() { - new enyo.Ajax({url: "index.html", handleAs: "text"}) - .response(this, function(inSender, inValue){ - this.finish(); - }) - .error(this, function(inSender, inValue) { - this.finish("bad status: " + inValue); - }) - .go(); - }, - testAjax404: function() { - new enyo.Ajax({url: "noexist.not"}) - .response(this, function(inSender, inValue){ - this.finish("ajax failed to fail"); - }) - .error(this, function(inSender, inValue) { - this.finish(); - }) - .go(); - }, - testAjaxCustomError: function() { - new enyo.Ajax({url: "appinfo.json"}) - .response(function(inSender, inValue){ - inSender.fail("cuz I said so"); - }) - .error(this, function(inSender, inValue) { - this.finish(); - }) - .go(); - }, - testAjaxSerial: function() { - // if the test finishes before ready, it's a failure - var ready = false; - // - // when 'index' request completes, we are 'ready' - var index = new enyo.Ajax({url: "index.html", handleAs: "text"}); - index.response(function() { - ready = true; - }); - // - // request triggers 'index' request when it completes - new enyo.Ajax({url: "index.html", handleAs: "text"}) - .response(index) - .response(this, function() { - // finish clean if 'ready' - this.finish(ready ? "" : "requests failed to complete in order"); - }) - .go(); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/AsyncTest.js b/enyo/tools/test/core/tests/AsyncTest.js deleted file mode 100644 index ac859d4..0000000 --- a/enyo/tools/test/core/tests/AsyncTest.js +++ /dev/null @@ -1,44 +0,0 @@ -enyo.kind({ - name: "AsyncTest", - kind: enyo.TestSuite, - testAsyncExists: function() { - new enyo.Async(); - this.finish(); - }, - testAsyncFail: function() { - var a = new enyo.Async(); - a.response(this, function(inSender, inValue) { - this.finish("error response not passed to success handler"); - }); - a.error(this, function() { - this.finish(); - }); - a.fail("foo"); - }, - testAsyncInnerFail: function() { - new enyo.Async() - .response(function(inSender, inValue) { - inSender.fail("always fail"); - }) - .error(this, function() { - this.finish(); - }) - .respond("foo") - ; - }, - testAsyncInnerFailRecover: function() { - new enyo.Async() - .response(function(inSender, inValue) { - inSender.fail("first response always fails"); - }) - .error(function(inSender) { - inSender.recover(); - return "recovery response"; - }) - .response(this, function(inSender, inValue) { - this.finish(inValue == "recovery response" ? null : "fail"); - }) - .respond("foo") - ; - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentDispatchTest.js b/enyo/tools/test/core/tests/ComponentDispatchTest.js deleted file mode 100644 index 4256514..0000000 --- a/enyo/tools/test/core/tests/ComponentDispatchTest.js +++ /dev/null @@ -1,74 +0,0 @@ -enyo.kind({ - name: "ComponentDispatchTest", - kind: enyo.TestSuite, - testDispatchEvent2NullArgs: function() { - var test = this; - var c = new enyo.Component({ - handlers: { - onOk: "ok" - }, - ok: function(inSender, inEvent) { - test.finish((inSender != c && "bad inSender") || (arguments.length !== 2 && "bad arguments")); - } - }); - c.dispatchEvent("onOk"); - }, - testDispatchEvent2OneArg: function() { - var test = this; - var c = new enyo.Component({ - handlers: { - onOk: "ok" - }, - ok: function(inSender, inEvent) { - test.finish((inSender != c && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); - } - }); - c.dispatchEvent("onOk", {value: 42}); - }, - testDispatchEvent2Owner: function() { - var test = this; - var c = new enyo.Component({ - components: [{ - name: "child", - onOk: "ok" - }], - ok: function(inSender, inEvent) { - test.finish((inSender != this.$.child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); - } - }); - c.$.child.dispatchEvent("onOk", {value: 42}); - }, - testBubble: function() { - var test = this; - var c = new enyo.Component({ - components: [{ - name: "child" - }], - handlers: { - onOk: "ok" - }, - ok: function(inSender, inEvent) { - test.finish((inSender != c.$.child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); - } - }); - c.$.child.bubble("onOk", {value: 42}); - }, - testDoubleBubble: function() { - var test = this; - var owner = new enyo.Component({ - handlers: { - onOk: "ok" - }, - ok: function(inSender, inEvent) { - test.finish((inSender != child && "bad inSender") || (inEvent.value !== 42 && "bad inValue")); - } - }); - var child = new enyo.Component({ - owner: owner - }); - var grandchild = new enyo.Component({ - owner: child - }); - grandchild.bubble("onOk", {value: 42}); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentHandlersTest.js b/enyo/tools/test/core/tests/ComponentHandlersTest.js deleted file mode 100644 index 1f4f716..0000000 --- a/enyo/tools/test/core/tests/ComponentHandlersTest.js +++ /dev/null @@ -1,22 +0,0 @@ -enyo.kind({ - name: "ComponentHandlersTest", - kind: enyo.TestSuite, - testHandlerUnion: function() { - enyo.kind({ - name: "TestBase", - kind: enyo.Component, - handlers: { - onOk: "ok" - } - }); - enyo.kind({ - name: "TestSub", - kind: TestBase, - handlers: { - onMore: "more" - } - }); - var h = new TestSub({handlers: {onFurther: "foo"}}).handlers; - this.finish((!h.onOk && "bad onOk") || (!h.onMore && "bad onMore") || (!h.onFurther && "bad onFurther")); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ComponentTest.js b/enyo/tools/test/core/tests/ComponentTest.js deleted file mode 100644 index 33e6e89..0000000 --- a/enyo/tools/test/core/tests/ComponentTest.js +++ /dev/null @@ -1,28 +0,0 @@ -enyo.kind({ - name: "ComponentTest", - kind: enyo.TestSuite, - testNestedComponentUndefinedKind: function() { - var pass = false; - // should throw exception as this is an error - try { - var a = enyo.kind( - { - name: "parentComponent", - components: [ - { - name: "nestedComponent", - kind: undefined - } - ] - } - ); - new a({}); - } catch(e) { - pass = true; - } - if (!pass) { - throw("no exception for explicitly undefined kind in a nested component"); - } - this.finish(); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ControlPropsTest.js b/enyo/tools/test/core/tests/ControlPropsTest.js deleted file mode 100644 index aa6d435..0000000 --- a/enyo/tools/test/core/tests/ControlPropsTest.js +++ /dev/null @@ -1,32 +0,0 @@ -enyo.kind({ - name: "ControlPropsTest", - kind: enyo.TestSuite, - testUnionAttributesStylesClasses: function() { - enyo.kind({ - name: "TestBase", - kind: enyo.Control, - attributes: { - a: 1 - }, - style: "a:1", - classes: "a" - }); - enyo.kind({ - name: "TestSub", - kind: TestBase, - attributes: { - b: 1 - }, - style: "b:1", - classes: "b" - }); - var t = new TestSub({attributes: {c: 1}, style: "c:1", classes: "c"}); - this.finish( - (!t.attributes.a && "bad a attr") || (!t.attributes.b && "bad b attr") || (!t.attributes.c && "bad c attr") - || - (!t.domStyles.a && "bad a style") || (!t.domStyles.b && "bad b style") /*|| (!t.domStyles.c && "bad c style")*/ - || - (t.attributes['class'] !== "a b c" && "bad classes, expected [a b c] got [" + t.attributes['class'] + "]") - ); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ControlTest.js b/enyo/tools/test/core/tests/ControlTest.js deleted file mode 100644 index bf96752..0000000 --- a/enyo/tools/test/core/tests/ControlTest.js +++ /dev/null @@ -1,92 +0,0 @@ -enyo.kind({ - name: "ControlTest", - kind: enyo.TestSuite, - testAddingComponents: function() { - var K = enyo.kind({ - kind: enyo.Control, - components: [ - { name: "a" }, - { name: "b" }, - { name: "c" } - ] - }); - - // create new div, attach to start of body, delete at end - // needed because we need live DOM with getElementById working - var div = document.createElement("div"); - document.body.appendChild(div); - - var k = new K(); - k.renderInto(div); - - var kn = div.firstChild; - try { - // basic tests of rendered nodes - if (k.hasNode() !== kn) { - throw("control node doesn't match rendering"); - } - if (kn.firstChild !== k.$.a.hasNode()) { - throw("a child not first node"); - } - if (kn.lastChild !== k.$.c.hasNode()) { - throw("c child not last node"); - } - // test deleting c - k.$.c.destroy(); - if (kn.lastChild !== k.$.b.hasNode()) { - throw("b child not last node after deletion"); - } - // add new node to end - var cc = k.createComponent({}); - cc.render(); - if (kn.lastChild !== cc.hasNode()) { - throw("added a child to end, not last node"); - } - // add new node before a (should be at start) - var aa = k.createComponent({}, {addBefore: k.$.a}); - aa.render(); - if (kn.firstChild !== aa.hasNode()) { - throw("added a child using node reference, not first node"); - } - // add another node to start using addBefore: null - var aaa = k.createComponent({}, {addBefore: null}); - aaa.render(); - if (kn.firstChild !== aaa.hasNode()) { - throw("added a child not first node"); - } - } finally { - // clean up after our test - k.destroy(); - document.body.removeChild(div); - } - this.finish(); - }, - testGetBounds: function() { - var K = enyo.kind({ - style: "position: absolute; top: 10px; height: 30px; left: 15px; width: 35px;" - }); - // create new div, attach to start of body, delete at end - // needed because we need live DOM with getElementById working - var div = document.createElement("div"); - document.body.appendChild(div); - - var k = new K(); - var b; - b = k.getBounds(); - if (b.top !== undefined || b.left !== undefined || b.height !== undefined || b.width !== undefined) { - throw("bad bounds, expected all undefined, got " + JSON.stringify(b)); - } - k.renderInto(div); - try { - b = k.getBounds(); - if (b.top !== 10 || b.left !== 15 || b.height !== 30 || b.width !== 35) { - throw("bad bounds, expected {top: 10, left: 15, height: 30, width: 35}, got " + JSON.stringify(b)); - } - } finally { - // clean up after our test - k.destroy(); - document.body.removeChild(div); - } - this.finish(); - } -}); diff --git a/enyo/tools/test/core/tests/DecodePackagePathTest.js b/enyo/tools/test/core/tests/DecodePackagePathTest.js deleted file mode 100644 index ce8e03c..0000000 --- a/enyo/tools/test/core/tests/DecodePackagePathTest.js +++ /dev/null @@ -1,70 +0,0 @@ -enyo.kind({ - name: "DecodePackagePathTest", - kind: enyo.TestSuite, - assert: function(inParts, inPart, inValue) { - if (inParts[inPart] != inValue) { - this.finish('bad ' + inPart + ', expected "' + inValue + '" got "' + inParts[inPart] + '"'); - return false; - } - return true; - }, - decodeTest: function(inPath, inExpected) { - var parts = enyo.loaderFactory.prototype.decodePackagePath(inPath); - for (var n in inExpected) { - if (!this.assert(parts, n, inExpected[n])) { - return; - } - } - this.finish(); - }, - testDecodeEmpty: function() { - this.decodeTest("", {folder: "", manifest: "package.js", alias: "", target: ""}); - }, - testDecodeFoo: function() { - this.decodeTest("foo", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); - }, - testDecodeFooSlash: function() { - this.decodeTest("foo/", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); - }, - testDecodeFooBackSlash: function() { - this.decodeTest("foo\\", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); - }, - testDecodeFooBarBaz: function() { - this.decodeTest("foo/bar/baz", {folder: "foo/bar/baz/", manifest: "foo/bar/baz/package.js", alias: "foo-bar-baz", target: "foo/bar/baz"}); - }, - testDecodeParentFoo: function() { - this.decodeTest("../foo", {folder: "../foo/", manifest: "../foo/package.js", alias: "foo", target: "../foo"}); - }, - testDecodeFooBarLibBaz: function() { - this.decodeTest("foo/bar/lib/baz", {folder: "foo/bar/lib/baz/", manifest: "foo/bar/lib/baz/package.js", alias: "baz", target: "foo/bar/lib/baz"}); - }, - testDecodeEnyoFoo: function() { - var $enyo = enyo.path.rewrite("$enyo"); - this.decodeTest($enyo + "/foo", {folder: $enyo + "foo/", manifest: $enyo + "foo/package.js", alias: "foo", target: $enyo + "foo"}); - }, - testDecodeAbsEnyoFoo: function() { - var $enyo = enyo.path.rewrite("$enyo") + "../enyo/"; - this.decodeTest($enyo + "foo", {folder: $enyo + "foo/", manifest: $enyo + "foo/package.js", alias: "foo", target: $enyo + "foo"}); - }, - testDecodeSource: function() { - this.decodeTest("source", {folder: "source/", manifest: "source/package.js", alias: "", target: ""}); - }, - testDecodeFooBarSource: function() { - this.decodeTest("foo/bar/source", {folder: "foo/bar/source/", manifest: "foo/bar/source/package.js", alias: "foo-bar", target: "foo/bar"}); - }, - testDecodeFooBarSourceZot: function() { - this.decodeTest("foo/bar/source/zot", {folder: "foo/bar/source/zot/", manifest: "foo/bar/source/zot/package.js", alias: "foo-bar-zot", target: "foo/bar/zot"}); - }, - testDecodeSourceFoo: function() { - this.decodeTest("source/foo", {folder: "source/foo/", manifest: "source/foo/package.js", alias: "foo", target: "foo"}); - }, - testLocalPackage: function() { - this.decodeTest("package.js", {folder: "", manifest: "package.js", alias: "", target: ""}); - }, - testFooPackage: function() { - this.decodeTest("foo/package.js", {folder: "foo/", manifest: "foo/package.js", alias: "foo", target: "foo"}); - }, - testRemote: function() { - this.decodeTest("http://flarn.com/lib/foo", {folder: "http://flarn.com/lib/foo/", manifest: "http://flarn.com/lib/foo/package.js", alias: "foo", target: "http://flarn.com/lib/foo"}); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/JsonTest.js b/enyo/tools/test/core/tests/JsonTest.js deleted file mode 100644 index 64a23f9..0000000 --- a/enyo/tools/test/core/tests/JsonTest.js +++ /dev/null @@ -1,36 +0,0 @@ -enyo.kind({ - name: "JSONTest", - kind: enyo.TestSuite, - testJsonStringifyExists: function() { - enyo.json.stringify(); - this.finish(); - }, - testJsonParseExists: function() { - enyo.json.parse(); - this.finish(); - }, - testJsonParseSimple: function() { - var obj = enyo.json.parse('{"foo":"bar"}'), err; - if (!obj.foo || obj.foo !== "bar") { - err = "JSON string did not parse correctly"; - } - this.finish(err); - }, - testJsonParseReviver: function() { - var dates = '{"hired":"2012-01-01T12:00:00Z","fired":"2012-01-02T12:00:00Z"}', - parsed = enyo.json.parse(dates, function(key, value) { - var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if ( a ) { - return new Date( - Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]) - ); - } - return value; - }), - err; - if (!(parsed.hired instanceof Date)) { - err = "JSON string did not parse and revive correctly"; - } - this.finish(err); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/KindTest.js b/enyo/tools/test/core/tests/KindTest.js deleted file mode 100644 index 266c760..0000000 --- a/enyo/tools/test/core/tests/KindTest.js +++ /dev/null @@ -1,41 +0,0 @@ -enyo.kind({ - name: "KindTest", - kind: enyo.TestSuite, - testNamespace: function() { - enyo.kind({name: "custom.Namespace"}); - Boolean(custom.Namespace); // throws an exception if namespace is undefined (Boolean() is just for lint) - this.finish(); - }, - testNullKind: function() { - // should succeed as this is allowed - var K = enyo.kind({kind: null}); - var i = new K({}); - this.finish(); - }, - testUndefinedKind: function() { - // should throw exception as this is an error - var pass = false; - try { - enyo.kind({kind: undefined}); - } catch(e) { - pass = true; - } - if (!pass) { - throw("no exception for explicitly undefined kind"); - } - this.finish(); - }, - testBadStringKind: function() { - // should throw exception as this is an error - var pass = false; - try { - enyo.kind({kind: "FooBarBaz"}); - } catch(e) { - pass = true; - } - if (!pass) { - throw("no exception for misnamed kind"); - } - this.finish(); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/LoaderTest.js b/enyo/tools/test/core/tests/LoaderTest.js deleted file mode 100644 index 9f2b7f7..0000000 --- a/enyo/tools/test/core/tests/LoaderTest.js +++ /dev/null @@ -1,28 +0,0 @@ -enyo.kind({ - name: "LoaderTest", - kind: enyo.TestSuite, - testSingleLoad: function() { - enyo.load("tests/loader1.js", enyo.bind(this, - function() { - if (window.LOADER_TEST === "loader1") { - this.finish(); - } - else { - this.finish("callback called before load complete"); - } - } - )); - }, - testMultipleLoad: function() { - enyo.load(["tests/loader2a.js", "tests/loader2b.js"], - enyo.bind(this, function() { - if (window.LOADER_TEST === "loader2b") { - this.finish(); - } - else { - this.finish("callback called before load complete"); - } - } - )); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/PathResolverTest.js b/enyo/tools/test/core/tests/PathResolverTest.js deleted file mode 100644 index d98676b..0000000 --- a/enyo/tools/test/core/tests/PathResolverTest.js +++ /dev/null @@ -1,57 +0,0 @@ -enyo.kind({ - name: "PathResolverTest", - kind: enyo.TestSuite, - rewriteTest: function(inResolver, inPath, inExpected) { - var pf= enyo.loader.packageFolder; - enyo.loader.packageFolder = "./source/"; - - var result = enyo.loader.getPathPrefix(inPath) + inResolver.rewrite(inPath); - - if (result === inExpected) { - this.finish(); - } else { - this.finish("Expected: '" + inExpected + "' Got: '" + result + "'"); - } - - enyo.loader.packageFolder = pf; - }, - testNormalPath: function() { - var resolver = new enyo.pathResolverFactory(); - this.rewriteTest(resolver, "my/folder", "./source/my/folder"); - }, - testLeadingSlashPath: function() { - var resolver = new enyo.pathResolverFactory(); - this.rewriteTest(resolver, "/my/folder", "/my/folder"); - }, - testRewriteHttps: function() { - var resolver = new enyo.pathResolverFactory(); - this.rewriteTest(resolver, "https://my.server/file.js", "https://my.server/file.js"); - }, - testRewriteHttpMixedCase: function() { - var resolver = new enyo.pathResolverFactory(); - this.rewriteTest(resolver, "hTtP://my.server/file.js", "hTtP://my.server/file.js"); - }, - testRewriteUnknown: function() { - var resolver = new enyo.pathResolverFactory(); - this.rewriteTest(resolver, "$enyo/package.js", "package.js"); - }, - testRewriteEnyo: function() { - var resolver = new enyo.pathResolverFactory(); - resolver.addPaths({enyo: "my-enyo-dir", lib: "$enyo/../lib"}); - this.rewriteTest(resolver, "$enyo/package.js", "my-enyo-dir/package.js"); - }, - testRewriteOnyx: function() { - var resolver = new enyo.pathResolverFactory(); - resolver.addPaths({enyo: "my-enyo-dir", lib: "$enyo/../lib"}); - this.rewriteTest(resolver, "$lib/onyx", "my-enyo-dir/../lib/onyx"); - }, - testRewriteEnyoPath: function() { - var input = "$lib/onyx"; - var result = enyo.path.rewrite(input); - if (result !== "onyx" && result != input) { - this.finish(); - } else { - this.finish("Got: '" + result + "'"); - } - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/ViewportPositioningTest.js b/enyo/tools/test/core/tests/ViewportPositioningTest.js deleted file mode 100644 index 96aa501..0000000 --- a/enyo/tools/test/core/tests/ViewportPositioningTest.js +++ /dev/null @@ -1,104 +0,0 @@ -enyo.kind({ - name: "ViewportPositioningTest", - kind: enyo.TestSuite, - - testMeasuringViewportCoordinates: function() { - var K = enyo.kind({ - kind: enyo.Control, - style: "position: absolute; top: 10px; left: 10px; width: 10px; height: 10px;" - }); - - // Similar to ControlTest, create a testing div to test DOM information with (delete at end) - var div = document.createElement("div"); - document.body.appendChild(div); - // Apply fixed positioning so that we know where things should be relative to the viewport - div.style.position = 'fixed'; - div.style.top = '0px'; - div.style.left = '0px'; - div.style.width = '100%'; - div.style.height = '100%'; - div.style.boxSizing = 'border-box'; - - var k = new K(); - k.renderInto(div); - - var p = enyo.dom.calcNodePosition(k.hasNode()), - // Bottom and right require calculating viewport size - fromBottom = (document.body.parentNode.offsetHeight > enyo.dom.getWindowHeight() ? enyo.dom.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight) - 20, - fromRight = (document.body.parentNode.offsetWidth > enyo.dom.getWindowWidth() ? enyo.dom.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth) - 20; - if (p.top !== 10) { - this.log('top failed with value: ' + p.top + ' (should be 10)'); - } - if (p.left !== 10) { - this.log('left failed with value: ' + p.left + ' (should be 10)'); - } - if (p.bottom !== fromBottom) { - this.log('bottom failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); - } - if (p.right !== fromRight) { - this.log('right failed with value: ' + p.right + ' (should be ' + fromRight + ')'); - } - if (p.width !== 10) { - this.log('width failed with value: ' + p.width + ' (should be 10)'); - } - if (p.height !== 10) { - this.log('height failed with value: ' + p.height + ' (should be 10)'); - } - - // Now test measuring the element when a parent has a border - div.style.border = "1px solid transparent"; - k.hasNode().style.border = "1px solid transparent"; - p = enyo.dom.calcNodePosition(k.hasNode()), - // We don't count the right border on the element itself because that is taken into account automatically by the element's width measurement - fromBottom -= 3, - fromRight -= 3; - if (p.top !== 11) { - this.log('top with border failed with value: ' + p.top + ' (should be 11)'); - } - if (p.left !== 11) { - this.log('left with border failed with value: ' + p.left + ' (should be 11)'); - } - if (p.bottom !== fromBottom) { - this.log('bottom with border failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); - } - if (p.right !== fromRight) { - this.log('right with border failed with value: ' + p.right + ' (should be ' + fromRight + ')'); - } - if (p.width !== 12) { - this.log('width with border failed with value: ' + p.width + ' (should be 12)'); - } - if (p.height !== 12) { - this.log('height with border failed with value: ' + p.height + ' (should be 12)'); - } - - // And finally, test positioning relative to another node - p = enyo.dom.calcNodePosition(k.hasNode(), div), - // Reset to div size - node height - fromBottom = div.offsetHeight - 22, - fromRight = div.offsetWidth - 22; - if (p.top !== 10) { - this.log('top relative to div failed with value: ' + p.top + ' (should be 10)'); - } - if (p.left !== 10) { - this.log('left relative to div failed with value: ' + p.left + ' (should be 10)'); - } - if (p.bottom !== fromBottom) { - this.log('bottom relative to div failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')'); - } - if (p.right !== fromRight) { - this.log('right relative to div failed with value: ' + p.right + ' (should be ' + fromRight + ')'); - } - if (p.width !== 12) { - this.log('width relative to div failed with value: ' + p.width + ' (should be 12)'); - } - if (p.height !== 12) { - this.log('height relative to div failed with value: ' + p.height + ' (should be 12)'); - } - - // Clean up - k.destroy(); - document.body.removeChild(div); - - this.finish(this.logMessages && this.logMessages.length ? 'Following measurements failed:' : ''); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/langTest.js b/enyo/tools/test/core/tests/langTest.js deleted file mode 100644 index ab7dde3..0000000 --- a/enyo/tools/test/core/tests/langTest.js +++ /dev/null @@ -1,54 +0,0 @@ -enyo.kind({ - name: "langTest", - kind: enyo.TestSuite, - testCallee: function() { - var err = ""; - var fn = function() { - err = (arguments.callee.nom !== 'fn'); - }; - fn.nom = "fn"; - fn(); - this.finish(err); - }, - testClass: function() { - enyo.kind({ - name: "AClass" - }); - var obj = new AClass(); - var err = (typeof AClass !== 'function'); - this.finish(err); - }, - testisString: function() { - - // Create alternate window context to write vars from - var iframe = document.createElement("iframe"), - iframeDoc, err; - - document.body.appendChild(iframe); - iframeDoc = iframe.contentDocument || iframe.contentWindow.document; - iframeDoc.write(""); - iframeDoc.close(); - - if (!enyo.isString("string")) { - err = "enyo.isString() cannot determine strings correctly"; - } - // This will fail: - // - instanceof from another context - // - typeof (b/c it is a string instance) - // https://github.com/enyojs/enyo/issues/2 - if (!enyo.isString(iString)) { - err = "enyo.isString() cannot determine strings written from other window contexts correctly"; - } - - document.body.removeChild(iframe); - this.finish(err); - }, - testindexOfRegular: function() { - var index = enyo.indexOf("foo", [null, null, null, null,"foo"]); - this.finish(index !== 4 ? "Incorrect index" : false); - }, - testindexOfFromIndex: function() { - var index = enyo.indexOf("foo", [null, null, null, null,"foo"], 10); - this.finish(index !== -1 ? "if fromIndex is greater then array length, should return -1" : false); - } -}); \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader1.js b/enyo/tools/test/core/tests/loader1.js deleted file mode 100644 index 1ce75aa..0000000 --- a/enyo/tools/test/core/tests/loader1.js +++ /dev/null @@ -1 +0,0 @@ -window.LOADER_TEST = "loader1"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader2a.js b/enyo/tools/test/core/tests/loader2a.js deleted file mode 100644 index f94de37..0000000 --- a/enyo/tools/test/core/tests/loader2a.js +++ /dev/null @@ -1 +0,0 @@ -window.LOADER_TEST = "loader2a"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/loader2b.js b/enyo/tools/test/core/tests/loader2b.js deleted file mode 100644 index c0f0391..0000000 --- a/enyo/tools/test/core/tests/loader2b.js +++ /dev/null @@ -1 +0,0 @@ -window.LOADER_TEST = "loader2b"; \ No newline at end of file diff --git a/enyo/tools/test/core/tests/package.js b/enyo/tools/test/core/tests/package.js deleted file mode 100644 index 522b3aa..0000000 --- a/enyo/tools/test/core/tests/package.js +++ /dev/null @@ -1,16 +0,0 @@ -enyo.depends( - "langTest.js", - //"LoaderTest.js", - "KindTest.js", - "JsonTest.js", - "AsyncTest.js", - "AjaxTest.js", - "ComponentTest.js", - "ComponentDispatchTest.js", - "ComponentHandlersTest.js", - "ControlTest.js", - "ControlPropsTest.js", - "DecodePackagePathTest.js", - "PathResolverTest.js", - "ViewportPositioningTest.js" -); diff --git a/gallery_images/Saramean.scheduler.jpg b/gallery_images/Saramean.scheduler.jpg deleted file mode 100644 index bfdd6915fe222d32cc9e147f47ec6c120e979a44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37999 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 BX}tgd diff --git a/index.html b/index.html index 5b07218..b48f515 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,113 @@ - - - Scheduler - - - - - - - - - - - - - - - - + + Enyo Community Gallery + + + + + + + + + + diff --git a/lib/layout/CONTRIBUTING md b/lib/layout/CONTRIBUTING md deleted file mode 100644 index cbc43fc..0000000 --- a/lib/layout/CONTRIBUTING md +++ /dev/null @@ -1,10 +0,0 @@ -# Contributions - -Contributions are welcome for Enyo and its associated libraries including onyx and layout. - -Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details -on our contribution policy and guidelines for use of the Enyo-DCO-1.0-Signed-off-by -line in your commits and pull requests. - -If you're interested in introducing new kinds, you might also consider hosting your own repo -and contributing to the [Enyo community gallery](http://enyojs.com/gallery). \ No newline at end of file diff --git a/lib/layout/README.md b/lib/layout/README.md deleted file mode 100644 index 43ce1f9..0000000 --- a/lib/layout/README.md +++ /dev/null @@ -1,71 +0,0 @@ -### Looking for the issue tracker? -It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). - ---- - -This is a layout library for Enyo 2. This library provides a collection of -layout functionality - -## List - -The list package provides a `List` control that displays a scrolling list of -rows. It's suitable for displaying very large lists and is optimized such that -only a small portion of the list is rendered at a given time. - -Check out the List samples in the Layout section of the -[Enyo Sampler](http://enyojs.com/sampler/) to see the control in action. For -more information, see the [List documentation](https://github.com/enyojs/enyo/wiki/Lists) -in the Enyo Developer Guide. - -## Fittable - -The fittable package helps you create layouts that expand to fit available -space--a common need for apps, but one that has historically been difficult -to meet using Web technologies. - -The `FittableColumns` and `FittableRows` controls let you define views whose -children are arranged either horizontally or vertically. Within a given view, -you can designate one child to expand and contract to fit the available space, -while its siblings retain their natural or explicitly-specified sizes. Fittable -views may be nested as needed. - -If you're thinking that this sounds a lot like a limited version of the CSS -Flexible Box Model, you're right. Our main objective was to provide a layout -model with capabilities similar to Flex Box, but with greater browser -compatibility. We also wanted to impose as few limitations as possible on the -CSS styling of child components, and to use JavaScript sparingly (we use it to -calculate the height of fittable elements, but otherwise leave the layout work -to the browser). - -As much as we like them, we want to emphasize that you should only use -`FittableColumns` and `FittableRows` when you need views to expand and -contract to fit available space. If you simply want to arrange elements -horizontally or vertically, you're better off employing standard Web layout -techniques. - -Check out the -[Fittable sample](http://enyojs.com/samples/fittable/app-layouts.html) to -see `FittableColumns` and `FittableRows` in action. - -## Panels - -The `enyo.Panels` kind is designed to satisfy a variety of common use cases -for application layout. Using `enyo.Panels`, controls may be arranged as -(among other things) a carousel, a set of collapsing panels, a card stack -that fades between panels, or a grid. - -For more information, see the [Panels documentation](https://github.com/enyojs/enyo/wiki/Panels) -on the Enyo wiki. - -## Slidable - -Slideable is a control that can be dragged either left-to-right or up-and-down -between a minimum and a maximum value. When released from dragging, a Slideable -will animate to its minimum or maximum position based on the direction dragged. - -## Tree - -Tree is a control showing a vertical list of labels with nesting and collapsing -of hierarchy levels. There's a simple example in the -[Enyo Sampler](http://enyojs.com/sampler/) showing the control in use as a -directory and file tree. \ No newline at end of file diff --git a/lib/layout/deploy.bat b/lib/layout/deploy.bat deleted file mode 100644 index e69de29..0000000 diff --git a/lib/layout/deploy.sh b/lib/layout/deploy.sh deleted file mode 100644 index e69de29..0000000 diff --git a/lib/layout/design.js b/lib/layout/design.js deleted file mode 100644 index 7016fa3..0000000 --- a/lib/layout/design.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - Descriptions to make layout kinds available in Ares. -*/ -Palette.model.push( - {name: "fittable", items: [ - {name: "FittableRows", description: "Vertical stacked layout", - inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ - {style: "background-color: lightblue; border: 1px dotted blue; height: 15px;"}, - {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, - {style: "background-color: lightblue; border: 1px dotted blue; height: 15px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "FittableRows"} - }, - {name: "FittableColumns", description: "Horizontal stacked layout", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightblue; border: 1px dotted blue; width: 20px;"}, - {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, - {style: "background-color: lightblue; border: 1px dotted blue; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "FittableColumns"} - } - ]}, - {name: "imageview", items: [ - {name: "ImageCarousel", description: "A carousel of images", - inline: {}, - config: {content: "$name", isContainer: true, kind: "ImageCarousel"} - }, - {name: "ImageView", description: "A scalable Image View", - inline: {}, - config: {content: "$name", isContainer: true, kind: "ImageView"} - }, - {name: "ImageViewPin", description: "An unscaled item inside an ImageView", - inline: {}, - config: {content: "$name", isContainer: true, kind: "ImageViewPin"} - }, - ]}, - {name: "List", items: [ - {name: "AroundList", description: "List with elements above the list", - inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} - ]}, - config: {content: "$name", isContainer: false, kind: "AroundList", onSetupItem: "", count: 0} - }, - {name: "List", description: "Infinite scrolling list", - inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} - ]}, - config: {content: "$name", isContainer: false, kind: "List", onSetupItem: "", count: 0} - }, - {name: "PulldownList", description: "List with pull-to-refresh", - inline: {kind: "FittableRows", style: "height: 80px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true, content: ". . ."}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"}, - {style: "background-color: lightgreen; border: 1px dotted green; height: 10px;"} - ]}, - config: {content: "$name", isContainer: false, kind: "PulldownList", onSetupItem: "", count: 0} - } - ]}, - {name: "Panels", items: [ - {name: "CardArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CardArranger"} - }, - {name: "CardSlideInArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CardSlideInArranger"} - }, - {name: "CarouselArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CarouselArranger"} - }, - {name: "CollapsingArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "CollapsingArranger", components: [ - {content: "Placeholder"} - ]} - }, - {name: "DockRightArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "DockRightArranger"} - }, - {name: "GridArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "GridArranger"} - }, - {name: "LeftRightArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "LeftRightArranger"} - }, - {name: "UpDownArranger", description: "Selectable sub-view", - inline: {kind: "FittableColumns", style: "height: 60px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightgreen; border: 1px dotted green;", fit: true}, - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"} - ]}, - config: {content: "$name", isContainer: true, kind: "Panels", arrangerKind: "UpDownArranger"} - }, - ]}, - {name: "Slideable", items: [ - {name: "Slideable", description: "Slideable sub-view", - inline: {kind: "FittableColumns", style: "height: 40px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightblue; border: 1px dotted blue;", fit: true} - ]}, - config: {content: "$name", isContainer: true, kind: "Slideable"} - } - ]}, - {name: "Tree", items: [ - {name: "Node", description: "A tree node", - inline: {kind: "FittableColumns", style: "height: 40px; position: relative;", padding: 4, components: [ - {style: "background-color: lightgreen; border: 1px dotted green; width: 20px;"}, - {style: "background-color: lightblue; border: 1px dotted blue;", fit: true}, - ]}, - config: {content: "$name", isContainer: true, kind: "Node"} - } - ]} -); \ No newline at end of file diff --git a/lib/layout/fittable/package.js b/lib/layout/fittable/package.js deleted file mode 100644 index 3fae95b..0000000 --- a/lib/layout/fittable/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "source" -); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout1.html b/lib/layout/fittable/samples/FittableAppLayout1.html deleted file mode 100644 index 173e15f..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout1.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Fittable App Layout 1 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout1.js b/lib/layout/fittable/samples/FittableAppLayout1.js deleted file mode 100644 index 21b9672..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout1.js +++ /dev/null @@ -1,21 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableAppLayout1", - kind: "FittableRows", - classes: "enyo-fit", - components: [ - {kind: "onyx.Toolbar", components: [ - {content: "Header"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input"} - ]} - ]}, - {kind: "FittableColumns", fit: true, components: [ - {style: "width: 30%;"}, - {kind: "FittableRows", fit: true, classes: "fittable-sample-shadow", components: [ - {classes: "fittable-sample-shadow2", style: "height: 30%; position: relative; z-index: 1;"}, - {fit: true, classes: "fittable-sample-fitting-color"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout2.html b/lib/layout/fittable/samples/FittableAppLayout2.html deleted file mode 100644 index cb9b652..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout2.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Fittable App Layout 2 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout2.js b/lib/layout/fittable/samples/FittableAppLayout2.js deleted file mode 100644 index 14a9f3a..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout2.js +++ /dev/null @@ -1,25 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableAppLayout2", - kind: "FittableColumns", - classes: "enyo-fit", - components: [ - {kind: "FittableRows", style: "width: 20%;", components: [ - {fit: true}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "1"} - ]} - ]}, - {kind: "FittableRows", style: "width: 20%;", classes: "fittable-sample-shadow", components: [ - {fit: true, style: ""}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "2"} - ]} - ]}, - {kind: "FittableRows", fit: true, classes: "fittable-sample-shadow", components: [ - {fit: true, classes: "fittable-sample-fitting-color"}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "3"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout3.html b/lib/layout/fittable/samples/FittableAppLayout3.html deleted file mode 100644 index 593a8f3..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout3.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Fittable App Layout 3 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout3.js b/lib/layout/fittable/samples/FittableAppLayout3.js deleted file mode 100644 index 2d8a0c1..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout3.js +++ /dev/null @@ -1,20 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableAppLayout3", - kind: "FittableColumns", - classes: "enyo-fit", - components: [ - {kind: "FittableRows", fit: true, components: [ - {fit: true, classes: "fittable-sample-fitting-color"}, - {classes: "fittable-sample-shadow3", style: "height: 30%; position: relative;"}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "1"} - ]} - ]}, - {kind: "FittableRows", classes: "fittable-sample-shadow", style: "width: 30%; position: relative;", components: [ - {fit: true}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "2"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout4.html b/lib/layout/fittable/samples/FittableAppLayout4.html deleted file mode 100644 index 3dfc7fa..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout4.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Fittable App Layout 4 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableAppLayout4.js b/lib/layout/fittable/samples/FittableAppLayout4.js deleted file mode 100644 index 5ab1532..0000000 --- a/lib/layout/fittable/samples/FittableAppLayout4.js +++ /dev/null @@ -1,21 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableAppLayout4", - kind: "FittableColumns", - classes: "enyo-fit", - components: [ - {kind: "FittableRows", classes: "fittable-sample-shadow4", style: "width: 30%; position: relative; z-index: 1;", components: [ - {style: "height: 20%;"}, - {style: "height: 20%;"}, - {fit: true}, - {kind: "onyx.Toolbar", style: "height: 57px;", components: [ - {content: "Toolbar"} - ]} - ]}, - {kind: "FittableRows", fit: true, components: [ - {fit: true, classes: "fittable-sample-fitting-color"}, - {kind: "onyx.Toolbar", style: "height: 57px;",components: [ - {kind: "onyx.Button", content: "2"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableDescription.html b/lib/layout/fittable/samples/FittableDescription.html deleted file mode 100644 index 5227fcc..0000000 --- a/lib/layout/fittable/samples/FittableDescription.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Fittables Description - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableDescription.js b/lib/layout/fittable/samples/FittableDescription.js deleted file mode 100644 index 3b66b6c..0000000 --- a/lib/layout/fittable/samples/FittableDescription.js +++ /dev/null @@ -1,44 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableDescription", - classes: "fittable-sample-box enyo-fit", - style: "padding:10px;", - kind: "Scroller", - components: [ - {tag: "p", allowHtml: true, content: "FittableColumns, no margin on boxes (all divs have some padding). By default, boxes 'stretch' to fit the container (which must have a height)."}, - {kind: "FittableColumns", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box"}, - {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box"}, - {content: "BoxC", classes: "fittable-sample-box"} - ]}, - {tag: "p", allowHtml: true, content: "Boxes with left/right margins. Note: top/bottom margin on column boxes is NOT supported."}, - {kind: "FittableColumns", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr"} - ]}, - {tag: "p", allowHtml: true, content: "With noStretch: true, boxes have natural height."}, - {kind: "FittableColumns", noStretch: true, classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "Fitting BoxB

    with natural height", fit: true, allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr"} - ]}, - {tag: "p", allowHtml: true, content: "FittableRows, no margin on boxes (all divs have some padding)."}, - {kind: "FittableRows", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box"}, - {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box"}, - {content: "BoxC", classes: "fittable-sample-box"} - ]}, - {tag: "p", allowHtml: true, content: "Row boxes may have margin in any dimension.

    NOTE: Row boxes will collapse vertical margins according to css rules. If margin collapse is not desired, then \"enyo-margin-expand\" may be applied. Only in this case, left/right margin on row boxes is NOT supported."}, - {kind: "FittableRows", classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mlr fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"} - ]}, - {tag: "p", allowHtml: true, content: "With noStretch: true, boxes have natural width.

    NOTE: margins will not collapse in this case."}, - {kind: "FittableRows", noStretch: true, classes: "fittable-sample-height fittable-sample-box fittable-sample-o fittable-sample-mtb", components: [ - {content: "BoxA", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {content: "Fitting BoxB", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {content: "BoxC", classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableSample.html b/lib/layout/fittable/samples/FittableSample.html deleted file mode 100644 index ecbe73c..0000000 --- a/lib/layout/fittable/samples/FittableSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Fittables Basic Sample - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableSample.js b/lib/layout/fittable/samples/FittableSample.js deleted file mode 100644 index c61fcfa..0000000 --- a/lib/layout/fittable/samples/FittableSample.js +++ /dev/null @@ -1,22 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableSample", - kind: "FittableRows", - classes: "fittable-sample-box enyo-fit", - components: [ - {content: "Foo
    Foo", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb"}, - {content: "Foo
    Foo", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb"}, - {kind: "FittableColumns", fit: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-o", components: [ - {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "Fits!", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, - {content: "Foo", classes: "fittable-sample-box fittable-sample-mlr"} - ]}, - {kind: "FittableColumns", content: "Bat", classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ - {content: "Centered", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "4", classes: "fittable-sample-box fittable-sample-mlr"} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableTests.html b/lib/layout/fittable/samples/FittableTests.html deleted file mode 100644 index 62a055b..0000000 --- a/lib/layout/fittable/samples/FittableTests.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Fittable Tests - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/fittable/samples/FittableTests.js b/lib/layout/fittable/samples/FittableTests.js deleted file mode 100644 index d4f148b..0000000 --- a/lib/layout/fittable/samples/FittableTests.js +++ /dev/null @@ -1,84 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FittableTests", - classes: "fittable-sample-box enyo-fit", - kind: "Scroller", - components: [ - {classes: "fittable-sample-section", content: "Rows/Columns using a combination of css units and highlighting margin collapse"}, - {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test", style: "height: 400px;", components: [ - {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-bottom: 1em;"}, - {content: "margin-top: 1em (collapsed since sibling shows greater of previous bottom and this top)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-top: 1em;"}, - {content: "FOO
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {kind: "FittableColumns", fit: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-mlr fittable-sample-o", components: [ - {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "2", fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, - {content: "3333333", classes: "fittable-sample-box fittable-sample-mlr"} - ]}, - {kind: "FittableColumns", content: "Bat", classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ - {content: "add enyo-center to FittableColumns", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "4", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "5", classes: "fittable-sample-box fittable-sample-mlr"} - ]} - ]}, - {classes: "fittable-sample-section", content: "Rows with enyo-margin-expand to avoid margin-collapse"}, - {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test enyo-margin-expand", style: "height: 250px;", components: [ - {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb", style: "margin-bottom: 1em;"}, - {content: "margin-top: 3em (not collapsed due to enyo-margin-expand on box)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mtb", style: "margin-top: 3em;"}, - {content: "FOO
    FOO", allowHtml: true, fit: true, classes: "fittable-sample-box fittable-sample-mtb"} - ]}, - {classes: "fittable-sample-section", content: "Tests to ensure fit region can be first, middle, or last"}, - {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A", fit: true}, - {content: "B"}, - {content: "C"} - ]}, - {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A"}, - {content: "B", fit: true}, - {content: "C"} - ]}, - {kind: "FittableRows", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A"}, - {content: "B"}, - {content: "C", fit: true} - ]}, - {kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A", fit: true}, - {content: "B"}, - {content: "C"} - ]}, - {kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A"}, - {content: "B", fit: true}, - {content: "C"} - ]}, - {style: "height: 200px;", kind: "FittableColumns", classes: "fittable-sample-boxable fittable-sample-small-test", components: [ - {content: "A"}, - {content: "B"}, - {content: "C", fit: true} - ]}, - {classes: "fittable-sample-section", content: "Tests for noStretch: true"}, - {kind: "FittableRows", classes: "fittable-sample-box fittable-sample-test", style: "height: 400px;", noStretch: true, components: [ - {content: "FOO
    margin-bottom: 1em", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-bottom: 1em;"}, - {content: "margin-top: 2em (not collapsed; stretch false does not collapse due to use of float)
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb", style: "margin-top: 1em;"}, - {content: "FOO
    FOO", allowHtml: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-mtb"}, - {kind: "FittableColumns", fit: true, noStretch: true, classes: "fittable-sample-box fittable-sample-mtb fittable-sample-mlr fittable-sample-o", components: [ - {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "111111111111111", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "2
    2", allowHtml: true, fit: true, classes: "fittable-sample-box fittable-sample-mlr fittable-sample-o"}, - {content: "3333333", classes: "fittable-sample-box fittable-sample-mlr"} - ]}, - {kind: "FittableColumns", content: "Bat", noStretch: true, classes: "fittable-sample-box fittable-sample-mtb enyo-center", components: [ - {content: "add enyo-center to FittableColumns", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "1", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "2", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "3", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "4", classes: "fittable-sample-box fittable-sample-mlr"}, - {content: "5", classes: "fittable-sample-box fittable-sample-mlr"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/layout/fittable/samples/package.js b/lib/layout/fittable/samples/package.js deleted file mode 100644 index 90784bd..0000000 --- a/lib/layout/fittable/samples/package.js +++ /dev/null @@ -1,9 +0,0 @@ -enyo.depends( - "sample.css", - "FittableSample.js", - "FittableAppLayout1.js", - "FittableAppLayout2.js", - "FittableAppLayout3.js", - "FittableAppLayout4.js", - "FittableDescription.js" -); \ No newline at end of file diff --git a/lib/layout/fittable/samples/sample.css b/lib/layout/fittable/samples/sample.css deleted file mode 100644 index c537a1e..0000000 --- a/lib/layout/fittable/samples/sample.css +++ /dev/null @@ -1,76 +0,0 @@ -.fittable-sample-box { - border: 2px solid lightblue; - padding: 4px; -} -.fittable-sample-b { - background-color: #F1FFF1; -} -.fittable-sample-mtb { - margin-top: 3px; - margin-bottom: 3px; -} -.fittable-sample-mlr { - margin-left: 6px; - margin-right: 6px; -} -.fittable-sample-o { - border-color: orange; -} -.fittable-sample-height { - height: 140px; -} - -.fittable-sample-fitting-color { - background: #B7BFC4; -} - -.fittable-sample-shadow { - box-shadow: -6px 0px 6px rgba(0,0,0,0.3); - -moz-box-shadow: -6px 0px 6px rgba(0,0,0,0.3); - -webkit-box-shadow: -6px 0px 6px rgba(0,0,0,0.3); -} - -.fittable-sample-shadow2 { - box-shadow: 6px 6px 6px rgba(0,0,0,0.3); - -moz-box-shadow: 6px 6px 6px rgba(0,0,0,0.3); - -webkit-box-shadow: 6px 6px 6px rgba(0,0,0,0.3); -} - -.fittable-sample-shadow3 { - box-shadow: 0 -6px 6px rgba(0,0,0,0.3); - -moz-box-shadow: 0 -6px 6px rgba(0,0,0,0.3); - -webkit-box-shadow: 0 -6px 6px rgba(0,0,0,0.3); -} - -.fittable-sample-shadow4 { - box-shadow: 6px 0px 6px rgba(0,0,0,0.3); - -moz-box-shadow: 6px 0px 6px rgba(0,0,0,0.3); - -webkit-box-shadow: 6px 0px 6px rgba(0,0,0,0.3); -} - -.fittable-sample-boxable { - margin: 0.5em; - padding: 1em; - border: 0.2em solid beige; -} - -.fittable-sample-boxable > * { - border: 0.1em dotted orange; - padding: 0.5em; -} - -.fittable-sample-test { - border-width: 0.2em; - border-color: red; -} - -.fittable-sample-small-test { - border-width: 0.2em; - border-color: red; - height: 150px; -} - -.fittable-sample-section { - padding: 30px 10px 10px; - font-weight: bold; -} \ No newline at end of file diff --git a/lib/layout/fittable/source/FittableColumns.js b/lib/layout/fittable/source/FittableColumns.js deleted file mode 100644 index ec138cf..0000000 --- a/lib/layout/fittable/source/FittableColumns.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - _enyo.FittableColumns_ provides a container in which items are laid out in a - set of vertical columns, with most items having natural size, but one - expanding to fill the remaining space. The one that expands is labeled with - the attribute _fit: true_. - - For more information, see the documentation on - [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo - Developer Guide. - -*/ - -enyo.kind({ - name: "enyo.FittableColumns", - layoutKind: "FittableColumnsLayout", - /** By default, items in columns stretch to fit vertically; set to true to - avoid this behavior */ - noStretch: false -}); diff --git a/lib/layout/fittable/source/FittableLayout.css b/lib/layout/fittable/source/FittableLayout.css deleted file mode 100644 index cdc24b8..0000000 --- a/lib/layout/fittable/source/FittableLayout.css +++ /dev/null @@ -1,69 +0,0 @@ -.enyo-fittable-rows-layout { - position: relative; -} - -.enyo-fittable-rows-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - /* float when not stretched */ - float: left; - clear: both; -} - -/* non-floating when stretched */ -.enyo-fittable-rows-layout.enyo-stretch > * { - float: none; - clear: none; -} - -/* setting to enforce margin collapsing */ -/* NOTE: rows cannot have margin left/right */ -.enyo-fittable-rows-layout.enyo-stretch.enyo-margin-expand > * { - float: left; - clear: both; - width: 100%; - /* note: harsh resets */ - margin-left: 0 !important; - margin-right: 0 !important; -} - -.enyo-fittable-columns-layout { - position: relative; - text-align: left; - white-space: nowrap; -} - -.enyo-fittable-columns-layout.enyo-center { - text-align: center; -} - -.enyo-fittable-columns-layout > * { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - vertical-align: top; - display: inline-block; - white-space: normal; -} - -.enyo-fittable-columns-layout.enyo-tool-decorator > * { - vertical-align: middle; -} - -/* repair clobbered white-space setting for pre, code */ -.enyo-fittable-columns-layout > pre, .enyo-fittable-columns-layout > code { - white-space: pre; -} - -.enyo-fittable-columns-layout > .enyo-fittable-columns-layout, .enyo-fittable-columns-layout > .onyx-toolbar-inline { - white-space: nowrap; -} - -/* NOTE: columns cannot have margin top/bottom */ -.enyo-fittable-columns-layout.enyo-stretch > * { - height: 100%; - /* note: harsh resets */ - margin-top: 0 !important; - margin-bottom: 0 !important; -} \ No newline at end of file diff --git a/lib/layout/fittable/source/FittableLayout.js b/lib/layout/fittable/source/FittableLayout.js deleted file mode 100644 index 412819c..0000000 --- a/lib/layout/fittable/source/FittableLayout.js +++ /dev/null @@ -1,156 +0,0 @@ -/** - _enyo.FittableLayout_ provides the base positioning and boundary logic for - the fittable layout strategy. The fittable layout strategy is based on - laying out items in either a set of rows or a set of columns, with most of - the items having natural size, but one item expanding to fill the remaining - space. The item that expands is labeled with the attribute _fit: true_. - - The subkinds enyo.FittableColumnsLayout - and enyo.FittableRowsLayout (or - their subkinds) are used for layout rather than _enyo.FittableLayout_ - because they specify properties that the framework expects to be available - when laying items out. - - For more information,see the documentation on - [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.FittableLayout", - kind: "Layout", - //* @protected - calcFitIndex: function() { - for (var i=0, c$=this.container.children, c; (c=c$[i]); i++) { - if (c.fit && c.showing) { - return i; - } - } - }, - getFitControl: function() { - var c$=this.container.children; - var f = c$[this.fitIndex]; - if (!(f && f.fit && f.showing)) { - this.fitIndex = this.calcFitIndex(); - f = c$[this.fitIndex]; - } - return f; - }, - getLastControl: function() { - var c$=this.container.children; - var i = c$.length-1; - var c = c$[i]; - while ((c=c$[i]) && !c.showing) { - i--; - } - return c; - }, - _reflow: function(measure, cMeasure, mAttr, nAttr) { - this.container.addRemoveClass("enyo-stretch", !this.container.noStretch); - var f = this.getFitControl(); - // no sizing if nothing is fit. - if (!f) { - return; - } - // - // determine container size, available space - var s=0, a=0, b=0, p; - var n = this.container.hasNode(); - // calculate available space - if (n) { - // measure 1 - p = enyo.dom.calcPaddingExtents(n); - // measure 2 - s = n[cMeasure] - (p[mAttr] + p[nAttr]); - //enyo.log("overall size", s); - } - // - // calculate space above fitting control - // measure 3 - var fb = f.getBounds(); - // offset - container padding. - a = fb[mAttr] - ((p && p[mAttr]) || 0); - //enyo.log("above", a); - // - // calculate space below fitting control - var l = this.getLastControl(); - if (l) { - // measure 4 - var mb = enyo.dom.getComputedBoxValue(l.hasNode(), "margin", nAttr) || 0; - if (l != f) { - // measure 5 - var lb = l.getBounds(); - // fit offset + size - var bf = fb[mAttr] + fb[measure]; - // last offset + size + ending margin - var bl = lb[mAttr] + lb[measure] + mb; - // space below is bottom of last item - bottom of fit item. - b = bl - bf; - } else { - b = mb; - } - } - - // calculate appropriate size for fit control - var fs = s - (a + b); - //enyo.log(f.id, fs); - // note: must be border-box; - f.applyStyle(measure, fs + "px"); - }, - //* @public - /** - Updates the layout to reflect any changes to contained components or the - layout container. - */ - reflow: function() { - if (this.orient == "h") { - this._reflow("width", "clientWidth", "left", "right"); - } else { - this._reflow("height", "clientHeight", "top", "bottom"); - } - } -}); - -/** - _enyo.FittableColumnsLayout_ provides a container in which items are laid - out in a set of vertical columns, with most of the items having natural - size, but one expanding to fill the remaining space. The one that expands is - labeled with the attribute _fit: true_. - - _enyo.FittableColumnsLayout_ is meant to be used as a value for the - _layoutKind_ property of other kinds. _layoutKind_ provides a way to add - layout behavior in a pluggable fashion while retaining the ability to use a - specific base kind. - - For more information, see the documentation on - [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.FittableColumnsLayout", - kind: "FittableLayout", - orient: "h", - layoutClass: "enyo-fittable-columns-layout" -}); - - -/** - _enyo.FittableRowsLayout_ provides a container in which items are laid out - in a set of horizontal rows, with most of the items having natural size, but - one expanding to fill the remaining space. The one that expands is labeled - with the attribute _fit: true_. - - _enyo.FittableRowsLayout_ is meant to be used as a value for the - _layoutKind_ property of other kinds. _layoutKind_ provides a way to add - layout behavior in a pluggable fashion while retaining the ability to use a - specific base kind. - - For more information, see the documentation on - [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.FittableRowsLayout", - kind: "FittableLayout", - layoutClass: "enyo-fittable-rows-layout", - orient: "v" -}); diff --git a/lib/layout/fittable/source/FittableRows.js b/lib/layout/fittable/source/FittableRows.js deleted file mode 100644 index c196349..0000000 --- a/lib/layout/fittable/source/FittableRows.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - _enyo.FittableRows_ provides a container in which items are laid out in a - set of horizontal rows, with most of the items having natural size, but one - expanding to fill the remaining space. The one that expands is labeled with - the attribute _fit: true_. - - For more information, see the documentation on - [Fittables](https://github.com/enyojs/enyo/wiki/Fittables) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.FittableRows", - layoutKind: "FittableRowsLayout", - /** By default, items in rows stretch to fit horizontally; set to true to - avoid this behavior */ - noStretch: false -}); diff --git a/lib/layout/fittable/source/package.js b/lib/layout/fittable/source/package.js deleted file mode 100644 index 74201af..0000000 --- a/lib/layout/fittable/source/package.js +++ /dev/null @@ -1,6 +0,0 @@ -enyo.depends( - "FittableLayout.css", - "FittableLayout.js", - "FittableRows.js", - "FittableColumns.js" -); \ No newline at end of file diff --git a/lib/layout/imageview/package.js b/lib/layout/imageview/package.js deleted file mode 100644 index 1adaff6..0000000 --- a/lib/layout/imageview/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "source/" -); diff --git a/lib/layout/imageview/samples/ImageCarouselSample.css b/lib/layout/imageview/samples/ImageCarouselSample.css deleted file mode 100644 index 7927029..0000000 --- a/lib/layout/imageview/samples/ImageCarouselSample.css +++ /dev/null @@ -1,8 +0,0 @@ -.imagecarousel-sample-input { - margin:0px 6px; -} - -.imagecarousel-sample-input input { - text-align:center; - width:30px; -} \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageCarouselSample.html b/lib/layout/imageview/samples/ImageCarouselSample.html deleted file mode 100644 index 1a6b27b..0000000 --- a/lib/layout/imageview/samples/ImageCarouselSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Image Carousel Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageCarouselSample.js b/lib/layout/imageview/samples/ImageCarouselSample.js deleted file mode 100644 index 84ba39d..0000000 --- a/lib/layout/imageview/samples/ImageCarouselSample.js +++ /dev/null @@ -1,74 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ImageCarouselSample", - kind: "FittableRows", - classes: "enyo-fit", - components: [ - {kind: "onyx.Toolbar", style:"text-align:center;", components: [ - {kind: "onyx.Button", content:"←", allowHtml: true, ontap:"previous"}, - {kind: "onyx.Button", content:"→", allowHtml: true, ontap:"next"}, - {kind: "onyx.InputDecorator", classes: "imagecarousel-sample-input", components: [ - {name: "carouselIndexInput", kind: "onyx.Input", value: "0", onchange: "updateIndex"} - ]} - ]}, - {name:"carousel", kind:"ImageCarousel", fit:true, onload:"load", onZoom:"zoom", onerror:"error", onTransitionStart: "transitionStart", onTransitionFinish: "transitionFinish"} - ], - create: function() { - this.inherited(arguments); - this.urls = [ - "assets/mercury.jpg", - "assets/venus.jpg", - "assets/earth.jpg", - "assets/mars.jpg", - "assets/jupiter.jpg", - "assets/saturn.jpg", - "assets/uranus.jpg", - "assets/neptune.jpg" - ]; - // although we're specifying all the image urls now, the images themselves - // only get created/loaded as needed - this.$.carousel.setImages(this.urls); - }, - load: function(inSender, inEvent) { - //enyo.log("image loaded: " + inEvent.originator.src); - }, - zoom: function(inSender, inEvent) { - //enyo.log("image zoomed: " + inEvent.scale + " scale on " + inEvent.originator.src); - }, - error: function(inSender, inEvent) { - //enyo.log("image error: " + inEvent.originator.src); - }, - transitionStart: function(inSender, inEvent) { - //enyo.log("image now transitioning from: " + this.$.carousel.getImageByIndex(inEvent.fromIndex).src - // + " to " + this.$.carousel.getImageByIndex(inEvent.toIndex).src); - }, - transitionFinish: function(inSender, inEvent) { - //enyo.log("image transitioned to: " + this.$.carousel.getActiveImage().src); - if (this.$.carouselIndexInput) { - this.$.carouselIndexInput.setValue(inEvent.toIndex); - } - }, - previous: function(inSender, inEvent) { - this.$.carousel.previous(); - }, - next: function(inSender, inEvent) { - this.$.carousel.next(); - }, - getRandomIndex: function() { - var i = Math.floor(Math.random()*this.$.carousel.images.length); - while(i==this.$.carousel.index) { //make sure it isn't the active index - i = Math.floor(Math.random()*this.$.carousel.images.length); - } - return i; - }, - updateIndex: function(inSender, inEvent) { - var index = this.trimWhitespace(this.$.carouselIndexInput.getValue()); - if(index === "" || isNaN(index)) { - //enyo.log("Numbers only please.") - return; - } - this.$.carousel.setIndex(parseInt(index, 10)); - }, - trimWhitespace: function(inString) { - return inString.replace(/^\s+|\s+$/g,""); - } -}); \ No newline at end of file diff --git a/lib/layout/imageview/samples/ImageViewSample.css b/lib/layout/imageview/samples/ImageViewSample.css deleted file mode 100644 index e69de29..0000000 diff --git a/lib/layout/imageview/samples/ImageViewSample.html b/lib/layout/imageview/samples/ImageViewSample.html deleted file mode 100644 index 1c8e7e5..0000000 --- a/lib/layout/imageview/samples/ImageViewSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Image View Sample - - - - - - - - - - - - - - - diff --git a/lib/layout/imageview/samples/ImageViewSample.js b/lib/layout/imageview/samples/ImageViewSample.js deleted file mode 100644 index 89ddd7b..0000000 --- a/lib/layout/imageview/samples/ImageViewSample.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - Our map pin icon is based in whole or in part on the OpenStructs open source information and documentation, - largely developed by Structured Dynamics LLC. You are free to use this content and system as you wish, so long - as any derivative works acknowledge these contributions. TechWiki is provided under the Creative Commons - Attribution License, version 3.0. - http://techwiki.openstructs.org/index.php/Open_Source_Icons -*/ -enyo.kind({ - name: "enyo.sample.ImageViewSample", - components: [ - {name:"sampleImageView", kind:"ImageView", src:"assets/globe.jpg", scale:"auto", classes:"enyo-fit", components: [ - {kind: "enyo.ImageViewPin", highlightAnchorPoint:true, anchor: {top:79, right:224}, position: {bottom:0, left:-16}, components: [ - {kind:"Image", src:"assets/pin.png"} - ]}, - {kind: "enyo.ImageViewPin", anchor: {top:280, left:415}, position: {bottom:0, right:-16}, components: [ - {kind:"Image", src:"assets/pin.png"} - ]}, - {kind: "enyo.ImageViewPin", highlightAnchorPoint:true, anchor: {bottom:"20%", left:"400px"}, position: {bottom:0, left:0}, components: [ - {style:"background:rgba(255,255,255,0.8);border:1px solid #888;margin:0px;padding:0px;width:300px", components: [ - {tag:"h3", content:"This is a text box"} - ]} - ]}, - {name:"testPin", kind: "enyo.ImageViewPin", anchor: {top:"10%", right:"10%"}, position: {top:0, left:0}, components: [ - {style:"border:1px solid yellow;width:10px;background:red;height:10px;"} - ]} - ]} - ] -}); - diff --git a/lib/layout/imageview/samples/assets/earth.jpg b/lib/layout/imageview/samples/assets/earth.jpg deleted file mode 100644 index 328e8c03934bf23de82c67845f4a18dbac4289fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157230 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 z 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
    lOFFHf*4gLWv||4EUJns(_; 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 z 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 diff --git a/lib/layout/imageview/samples/assets/mars.jpg b/lib/layout/imageview/samples/assets/mars.jpg deleted file mode 100644 index f192d7a0783bbc642c6ae22a6e7f73bba6e6e5d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116236 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 LCjUoX^zi=!5b`-3 diff --git a/lib/layout/imageview/samples/assets/mercury.jpg b/lib/layout/imageview/samples/assets/mercury.jpg deleted file mode 100644 index e9dc766ee464237308679ab9f55859ea7e44e927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206369 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 L|9c(&{q_F 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

    0;G?5tocoJ2aCaLN#5IFj22y%<#o*SV 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 diff --git a/lib/layout/list/samples/assets/item-hilite.png b/lib/layout/list/samples/assets/item-hilite.png deleted file mode 100644 index 7e9c07d40c6acf1f4936f556f48125d81a7d579b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^4nQ2n!3HGjpG}AWQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtZVz*NBqf{Irtt#G+J&fW*wa5h zJyShH1A{L`3xUS=c)B=-RK&f#eBJS|gMjPBmCn;rJ$Vy_ea@LBXf(+9`l&5XYu{da z=cfhhp52?n-v6i%xI`)X~z zdN;#Vy@oTZ&guhMPp`5hu zo7GoY3nF)}`p`9O^E83Z z&G4CPHFM(eSHukG$2)R4xZG#!crM zCreh=+>!&b_U&Vso|@as-pvqM?Js^{Dffdu|J%wAX3Mx4j6eO@63bXt${6$i@*Bfr U>GAKD0b`HB)78&qol`;+02l7vssI20 diff --git a/lib/layout/list/samples/assets/pulldown.png b/lib/layout/list/samples/assets/pulldown.png deleted file mode 100644 index 1a452097fcbea95ae9b59949149c81b7a107dfdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3031 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 diff --git a/lib/layout/list/samples/assets/search-input-search.png b/lib/layout/list/samples/assets/search-input-search.png deleted file mode 100644 index 36bf1b5161e9d6b22273b681e43c85859c7c8914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/lib/layout/list/samples/assets/spinner.gif b/lib/layout/list/samples/assets/spinner.gif deleted file mode 100644 index b412a684db625390e8dbbe8be69262dbf3b19ddd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 664 zcmZ?wbhEHbeMM79-hgQC)?WEPMtb+{rdG)RaH-(JUMsn+|#E|jg5^N z7#L>GoSBxEcIM2P|Ns9h{^#~{4GDI33~)8lGhk)}N-O?kVdVmvrUPUHDSie97N-v< zGpEh8XczsY!u2sE{E^Cy1w4|E6lN^oxcN{fu20l=q5U$Khm)QnGb{K^KWY1ZGy>f3j8qEXrAYw_(GDG+gX1D$CnAG+*uHwVgs7P2@Wd*gPmVi zx$;F;->GC^&Jj(Xw4h^M^hJ>j<;8ku@>-l0G#iDqwLVk~;LvJxWe}B_q=YbpiGc~> z7|qGvCiYJzENd^WN%_gZlVG%_bJemG9k(!(RuLV?Yk!PxH7`)G$=i9x!O(zHgvl4l zF$@fBK&OBL#^8d^=T%!zF5PhGZ%4Dom2}y2iR;7{3dkQ|xW0f#esO%0l1;1IL&e2w zr97^wTKsWA3K<5tV@y8SZtmIhqgAwM*);X87N?#|3wT~AYdC2qy9TFpPWJGfugKT3 Wq>R~sp}+a@gG7sHw *:first-child { - padding-top: 4px; - border-radius: 12px 12px 0 0; - border-top: 1px solid #333; -} - -.enyo-alpha-jumper > *:last-child { - padding-bottom: 4px; - border-radius: 0 0 12px 12px; - border-bottom: 1px solid #333; -} - -.enyo-alpha-jumper > * { - background: #eee; - padding: 1px 4px; - border-right: 1px solid #333; - border-left: 1px solid #333; -} - -.enyo-alpha-jumper > .active { - background: #333; - color: white; -} \ No newline at end of file diff --git a/lib/layout/list/source/AlphaJumper.js b/lib/layout/list/source/AlphaJumper.js deleted file mode 100644 index 13cf843..0000000 --- a/lib/layout/list/source/AlphaJumper.js +++ /dev/null @@ -1,70 +0,0 @@ -enyo.kind({ - name: "enyo.AlphaJumper", - classes: "enyo-alpha-jumper enyo-border-box", - published: { - marker: null - }, - events: { - onAlphaJump: "" - }, - handlers: { - ondown: "down", - onmove: "move", - onup: "up" - }, - initComponents: function() { - for (var s="A".charCodeAt(0), i=s; ienyo.List that allows - content to be displayed around its rows. - - {kind: "enyo.AroundList", onSetupItem: "setupItem", - aboveComponents: [ - {content: "Content above the list"} - ], - components: [ - {content: "List item"} - ] - } -*/ -enyo.kind({ - name: "enyo.AroundList", - kind: "enyo.List", - //* @protected - listTools: [ - {name: "port", classes: "enyo-list-port enyo-border-box", components: [ - {name: "aboveClient"}, - {name: "generator", kind: "FlyweightRepeater", canGenerate: false, components: [ - {tag: null, name: "client"} - ]}, - {name: "holdingarea", allowHtml: true, classes: "enyo-list-holdingarea"}, - {name: "page0", allowHtml: true, classes: "enyo-list-page"}, - {name: "page1", allowHtml: true, classes: "enyo-list-page"}, - {name: "belowClient"}, - {name: "placeholder"}, - {name: "swipeableComponents", style: "position:absolute; display:block; top:-1000px; left:0px;"} - ]} - ], - //* @public - //* Block of components to be rendered above the list - aboveComponents: null, - //* @protected - initComponents: function() { - this.inherited(arguments); - if (this.aboveComponents) { - this.$.aboveClient.createComponents(this.aboveComponents, {owner: this.owner}); - } - if (this.belowComponents) { - this.$.belowClient.createComponents(this.belowComponents, {owner: this.owner}); - } - }, - updateMetrics: function() { - this.defaultPageHeight = this.rowsPerPage * (this.rowHeight || 100); - this.pageCount = Math.ceil(this.count / this.rowsPerPage); - this.aboveHeight = this.$.aboveClient.getBounds().height; - this.belowHeight = this.$.belowClient.getBounds().height; - this.portSize = this.aboveHeight + this.belowHeight; - for (var i=0; i < this.pageCount; i++) { - this.portSize += this.getPageHeight(i); - } - this.adjustPortSize(); - }, - positionPage: function(inPage, inTarget) { - inTarget.pageNo = inPage; - var y = this.pageToPosition(inPage); - var o = this.bottomUp ? this.belowHeight : this.aboveHeight; - y += o; - inTarget.applyStyle(this.pageBound, y + "px"); - }, - scrollToContentStart: function() { - var y = this.bottomUp ? this.belowHeight : this.aboveHeight; - this.setScrollPosition(y); - } -}); \ No newline at end of file diff --git a/lib/layout/list/source/FlyweightRepeater.js b/lib/layout/list/source/FlyweightRepeater.js deleted file mode 100644 index b6cd9ce..0000000 --- a/lib/layout/list/source/FlyweightRepeater.js +++ /dev/null @@ -1,248 +0,0 @@ -/** - _enyo.FlyweightRepeater_ is a control that displays a repeating list of - rows, suitable for displaying medium-sized lists (up to ~100 items). A - flyweight strategy is employed to render one set of row controls, as needed, - for as many rows as are contained in the repeater. - - The FlyweightRepeater's _components_ block contains the controls to be used - for a single row. This set of controls will be rendered for each row. You - may customize row rendering by handling the _onSetupItem_ event. - - The controls inside a FlyweightRepeater are non-interactive. This means that - calling methods that would normally cause rendering to occur (e.g., - _setContent_) will not do so. However, you can force a row to render by - calling _renderRow(inRow)_. - - In addition, you can force a row to be temporarily interactive by calling - _prepareRow(inRow)_. Call the _lockRow_ method when the interaction is - complete. - - For more information, see the documentation on - [Lists](https://github.com/enyojs/enyo/wiki/Lists) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.FlyweightRepeater", - published: { - //* Number of rows to render - count: 0, - /** - If true, the selection mechanism is disabled. Tap events are still - sent, but items won't be automatically re-rendered when tapped. - */ - noSelect: false, - //* If true, multiple selections are allowed - multiSelect: false, - //* If true, the selected item will toggle - toggleSelected: false, - /** - Used to specify CSS classes for the repeater's wrapper component - (client). Input is identical to enyo.Control.setClasses() - */ - clientClasses: '', - /** - Used to specify custom styling for the repeater's wrapper component - (client). Input is identical to enyo.Control.setStyle() - */ - clientStyle: '', - /** - Offset applied to row number during generation. Used to allow a - items to use a natural index instead of being forced to be - 0-based. Must be positive, as row -1 is used for undefined rows - in the event system. - */ - rowOffset: 0 - }, - events: { - /** - Fires once per row at render time. - - _inEvent.index_ contains the current row index. - - _inEvent.selected_ is a boolean indicating whether the current row - is selected. - */ - onSetupItem: "", - //* Fires after an individual row has been rendered from a call to _renderRow()_. - onRenderRow: "" - }, - //* design-time attribute, indicates if row indices run - //* from [0.._count_-1] (false) or [_count_-1..0] (true) - bottomUp: false, - //* @protected - components: [ - {kind: "Selection", onSelect: "selectDeselect", onDeselect: "selectDeselect"}, - {name: "client"} - ], - create: function() { - this.inherited(arguments); - this.noSelectChanged(); - this.multiSelectChanged(); - this.clientClassesChanged(); - this.clientStyleChanged(); - }, - noSelectChanged: function() { - if (this.noSelect) { - this.$.selection.clear(); - } - }, - multiSelectChanged: function() { - this.$.selection.setMulti(this.multiSelect); - }, - clientClassesChanged: function() { - this.$.client.setClasses(this.clientClasses); - }, - clientStyleChanged: function() { - this.$.client.setStyle(this.clientStyle); - }, - setupItem: function(inIndex) { - this.doSetupItem({index: inIndex, selected: this.isSelected(inIndex)}); - }, - //* Renders the list. - generateChildHtml: function() { - var h = ""; - this.index = null; - // note: can supply a rowOffset - // and indicate if rows should be rendered top down or bottomUp - for (var i=0, r=0; i= this.count + this.rowOffset) { - return; - } - //this.index = null; - // always call the setupItem callback, as we may rely on the post-render state - this.setupItem(inIndex); - var node = this.fetchRowNode(inIndex); - if (node) { - enyo.dom.setInnerHtml(node, this.$.client.generateChildHtml()); - this.$.client.teardownChildren(); - this.doRenderRow({rowIndex: inIndex}); - } - }, - //* Fetches the DOM node for the given row index. - fetchRowNode: function(inIndex) { - if (this.hasNode()) { - return this.node.querySelector('[data-enyo-index="' + inIndex + '"]'); - } - }, - //* Fetches the row number corresponding with the target of a given event. - rowForEvent: function(inEvent) { - if (!this.hasNode()) { - return -1; - } - var n = inEvent.target; - while (n && n !== this.node) { - var i = n.getAttribute && n.getAttribute("data-enyo-index"); - if (i !== null) { - return Number(i); - } - n = n.parentNode; - } - return -1; - }, - //* Prepares the row specified by _inIndex_ such that changes made to the - //* controls inside the repeater will be rendered for the given row. - prepareRow: function(inIndex) { - // do nothing if index is out-of-range - if (inIndex < 0 || inIndex >= this.count) { - return; - } - // update row internals to match model - this.setupItem(inIndex); - var n = this.fetchRowNode(inIndex); - enyo.FlyweightRepeater.claimNode(this.$.client, n); - }, - //* Prevents rendering of changes made to controls inside the repeater. - lockRow: function() { - this.$.client.teardownChildren(); - }, - //* Prepares the row specified by _inIndex_ such that changes made to the - //* controls in the row will be rendered in the given row; then performs the - //* function _inFunc_, and, finally, locks the row. - performOnRow: function(inIndex, inFunc, inContext) { - // do nothing if index is out-of-range - if (inIndex < 0 || inIndex >= this.count) { - return; - } - if (inFunc) { - this.prepareRow(inIndex); - enyo.call(inContext || null, inFunc); - this.lockRow(); - } - }, - statics: { - //* Associates a flyweight rendered control (_inControl_) with a - //* rendering context specified by _inNode_. - claimNode: function(inControl, inNode) { - var n; - if (inNode) { - if (inNode.id !== inControl.id) { - n = inNode.querySelector("#" + inControl.id); - } - else { - // inNode is already the right node, so just use it - n = inNode; - } - } - // FIXME: consider controls generated if we found a node or tag: null, the later so can teardown render - inControl.generated = Boolean(n || !inControl.tag); - inControl.node = n; - if (inControl.node) { - inControl.rendered(); - } else { - //enyo.log("Failed to find node for", inControl.id, inControl.generated); - } - // update control's class cache based on the node contents - for (var i=0, c$=inControl.children, c; (c=c$[i]); i++) { - this.claimNode(c, inNode); - } - } - } -}); \ No newline at end of file diff --git a/lib/layout/list/source/List.css b/lib/layout/list/source/List.css deleted file mode 100644 index c3baf0d..0000000 --- a/lib/layout/list/source/List.css +++ /dev/null @@ -1,49 +0,0 @@ -.enyo-list { - position: relative; -} - -.enyo-list-port { - overflow: hidden; - position: relative; - height: 1000000px; -} - -.enyo-list-page, .enyo-list-holdingarea { - position: absolute; - left: 0; - right: 0; -} - -.enyo-list-holdingarea { - top: -10000px; -} - -.enyo-pinned-list-placeholder { - border: 1px solid red; - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-pinned-list-placeholder button { - width: 100px; height: 100%; - position: absolute; - top: 0; right: 0; -} - -.enyo-list-reorder-container { - position: absolute; - top: 0; left: 0; - z-index: 1000; - background: transparent; - overflow: hidden; -} - -.enyo-animatedTopAndLeft { - -webkit-transition: top 0.1s linear, left 0.1s linear; - -moz-transition: top 0.1s linear, left 0.1s linear; - -o-transition: top 0.1s linear, left 0.1s linear; - transition: top 0.1s linear, left 0.1s linear; -} \ No newline at end of file diff --git a/lib/layout/list/source/List.js b/lib/layout/list/source/List.js deleted file mode 100644 index 70d714d..0000000 --- a/lib/layout/list/source/List.js +++ /dev/null @@ -1,1502 +0,0 @@ -/** - _enyo.List_ is a control that displays a scrolling list of rows, suitable - for displaying very large lists. It is optimized such that only a small - portion of the list is rendered at a given time. A flyweight pattern is - employed, in which controls placed inside the list are created once, but - rendered for each list item. For this reason, it's best to use only simple - controls in a List, such as enyo.Control and - enyo.Image. - - A List's _components_ block contains the controls to be used for a single - row. This set of controls will be rendered for each row. You may customize - row rendering by handling the _onSetupItem_ event. - - Events fired from within list rows contain the _index_ property, which may - be used to identify the row from which the event originated. - - Beginning with Enyo 2.2, lists have built-in support for swipeable and - reorderable list items. Individual list items are swipeable by default; to - enable reorderability, set the _reorderable_ property to true. - - For more information, see the documentation on - [Lists](https://github.com/enyojs/enyo/wiki/Lists) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.List", - kind: "Scroller", - classes: "enyo-list", - published: { - /** - The number of rows contained in the list. Note that as the amount of - list data changes, _setRows_ can be called to adjust the number of - rows. To re-render the list at the current position when the count - has changed, call the _refresh_ method. If the whole data model of - the list has changed and you want to redisplay from the top, call - the _reset_ method instead. - */ - count: 0, - /** - The number of rows to be shown on a given list page segment. - There is generally no need to adjust this value. - */ - rowsPerPage: 50, - /** - If true, renders the list such that row 0 is at the bottom of the - viewport and the beginning position of the list is scrolled to the - bottom - */ - bottomUp: false, - /** - If true, the selection mechanism is disabled. Tap events are still - sent, but items won't be automatically re-rendered when tapped. - */ - noSelect: false, - //* If true, multiple selections are allowed - multiSelect: false, - //* If true, the selected item will toggle - toggleSelected: false, - //* If true, the list will assume all rows have the same height for optimization - fixedHeight: false, - //* If true, the list will allow the user to reorder list items - reorderable: false, - //* If true and _reorderable_ is true, reorderable item will be centered on finger - //* when created. When false, it will be created over old item and will then track finger. - centerReorderContainer: true, - //* Array containing components shown as the placeholder when reordering list items. - reorderComponents: [], - //* Array containing components for the pinned version of a row. If not provided, reordering - //* will not support pinned mode. - pinnedReorderComponents: [], - //* Array containing any swipeable components that will be used - swipeableComponents: [], - //* If true, swipe functionality is enabled - enableSwipe: false, - //* If true, tells list to persist the current swipeable item - persistSwipeableItem: false - }, - events: { - /** - Fires once per row at render time. - _inEvent.index_ contains the current row index. - */ - onSetupItem: "", - //* Reorder events - onSetupReorderComponents: "", - onSetupPinnedReorderComponents: "", - onReorder: "", - //* Swipe events - onSetupSwipeItem: "", - onSwipeDrag: "", - onSwipe: "", - onSwipeComplete: "" - }, - handlers: { - onAnimateFinish: "animateFinish", - onRenderRow: "rowRendered", - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish", - onup: "up", - onholdpulse: "holdpulse" - }, - //* @protected - rowHeight: 0, - listTools: [ - {name: "port", classes: "enyo-list-port enyo-border-box", components: [ - {name: "generator", kind: "FlyweightRepeater", canGenerate: false, components: [ - {tag: null, name: "client"} - ]}, - {name: "holdingarea", allowHtml: true, classes: "enyo-list-holdingarea"}, - {name: "page0", allowHtml: true, classes: "enyo-list-page"}, - {name: "page1", allowHtml: true, classes: "enyo-list-page"}, - {name: "placeholder"}, - {name: "swipeableComponents", style: "position:absolute; display:block; top:-1000px; left:0;"} - ]} - ], - - //* Reorder vars - // how long, in ms, to wait for to active reordering - reorderHoldTimeMS: 600, - // index of the row that we're moving - draggingRowIndex: -1, - // node of the dragged row, used to keep touch events alive - draggingRowNode: null, - // index of the row before which we'll show the placeholder item. If the placeholder - // is at the end of the list, this will be one larger than the row count. - placeholderRowIndex: -1, - // determines scroll height at top/bottom of list where dragging will cause scroll - dragToScrollThreshold: 0.1, - // used to determine direction of scrolling during reordering - prevScrollTop: 0, - // how many MS between scroll events when autoscrolling - autoScrollTimeoutMS: 20, - // holds timeout ID for autoscroll - autoScrollTimeout: null, - // keep last event Y coordinate to update placeholder position during autoscroll - autoscrollPageY: 0, - // set to true to indicate that we're in pinned reordering mode - pinnedReorderMode: false, - // y-coordinate of the original location of the pinned row - initialPinPosition: -1, - // set to true after drag-and-drop has moved the reordering item at least one space - // used to activate pin mode if item is dropped immediately - itemMoved: false, - // this tracks the page where the being-dragged item is so we can detect - // when we switch pages and need to adjust rendering - currentPageNumber: -1, - // timeout for completing reorder operation - completeReorderTimeout: null, - - //* Swipeable vars - // Index of swiped item - swipeIndex: null, - // Direction of swipe - swipeDirection: null, - // True if a persistent item is currently persisting - persistentItemVisible: false, - // Side from which the persisting item came - persistentItemOrigin: null, - // True if swipe was completed - swipeComplete: false, - // Timeout used to wait before completing swipe action - completeSwipeTimeout: null, - // Time in MS to wait before completing swipe action - completeSwipeDelayMS: 500, - // Time in MS for normal swipe animation - normalSwipeSpeedMS: 200, - // Time in seconds for fast swipe animation - fastSwipeSpeedMS: 100, - // Percentage of a swipe needed to force completion of the swipe - percentageDraggedThreshold: 0.2, - - importProps: function(inProps) { - // force touch on desktop when we have reorderable items to work around - // problems with native scroller - if (inProps && inProps.reorderable) { - this.touch = true; - } - this.inherited(arguments); - }, - create: function() { - this.pageHeights = []; - this.inherited(arguments); - this.getStrategy().translateOptimized = true; - this.bottomUpChanged(); - this.noSelectChanged(); - this.multiSelectChanged(); - this.toggleSelectedChanged(); - // setup generator to default to "full-list" values - this.$.generator.setRowOffset(0); - this.$.generator.setCount(this.count); - }, - initComponents: function() { - this.createReorderTools(); - this.inherited(arguments); - this.createSwipeableComponents(); - }, - createReorderTools: function() { - this.createComponent({ - name: "reorderContainer", classes: "enyo-list-reorder-container", - ondown: "sendToStrategy", ondrag: "sendToStrategy", - ondragstart: "sendToStrategy", ondragfinish: "sendToStrategy", - onflick: "sendToStrategy"}); - }, - createStrategy: function() { - this.controlParentName = "strategy"; - this.inherited(arguments); - this.createChrome(this.listTools); - this.controlParentName = "client"; - this.discoverControlParent(); - }, - createSwipeableComponents: function() { - for(var i=0;i= this.reorderHoldTimeMS) { - // determine if we should handle the hold event - if(this.shouldStartReordering(inSender, inEvent)) { - inEvent.preventDefault(); - this.startReordering(inEvent); - return false; - } - } - }, - //* DragStart event handler - dragstart: function(inSender, inEvent) { - // stop dragstart from propogating if we're in reorder mode - if (this.isReordering()) { - return true; - } - if (this.isSwipeable()) { - return this.swipeDragStart(inSender, inEvent); - } - }, - //* Drag event handler - drag: function(inSender, inEvent) { - // determine if we should handle the drag event - if(this.shouldDoReorderDrag(inEvent)) { - inEvent.preventDefault(); - this.reorderDrag(inEvent); - return true; - } - else if (this.isSwipeable()) { - inEvent.preventDefault(); - this.swipeDrag(inSender, inEvent); - return true; - } - }, - //* Dragfinish event handler - dragfinish: function(inSender, inEvent) { - if(this.isReordering()) { - this.finishReordering(inSender, inEvent); - } - else if (this.isSwipeable()) { - this.swipeDragFinish(inSender, inEvent); - } - }, - //* up event handler - up: function(inSender, inEvent) { - if(this.isReordering()) { - this.finishReordering(inSender, inEvent); - } - }, - generatePage: function(inPageNo, inTarget) { - this.page = inPageNo; - var r = this.rowsPerPage * this.page; - this.$.generator.setRowOffset(r); - var rpp = Math.min(this.count - r, this.rowsPerPage); - this.$.generator.setCount(rpp); - var html = this.$.generator.generateChildHtml(); - inTarget.setContent(html); - // prevent reordering row from being draw twice - if(this.getReorderable() && this.draggingRowIndex > -1) { - this.hideReorderingRow(); - } - var pageHeight = inTarget.getBounds().height; - // if rowHeight is not set, use the height from the first generated page - if (!this.rowHeight && pageHeight > 0) { - this.rowHeight = Math.floor(pageHeight / rpp); - this.updateMetrics(); - } - // update known page heights - if (!this.fixedHeight) { - var h0 = this.getPageHeight(inPageNo); - this.pageHeights[inPageNo] = pageHeight; - this.portSize += pageHeight - h0; - } - }, - //* map a row index number to the page number it would be in - pageForRow: function(inIndex) { - return Math.floor(inIndex / this.rowsPerPage); - }, - // preserve original DOM node because it may be needed to route touch events - preserveDraggingRowNode: function(pageNo) { - if (this.draggingRowNode && this.pageForRow(this.draggingRowIndex) === pageNo) { - this.$.holdingarea.hasNode().appendChild(this.draggingRowNode); - this.draggingRowNode = null; - this.removedInitialPage = true; - } - }, - update: function(inScrollTop) { - var updated = false; - // get page info for position - var pi = this.positionToPageInfo(inScrollTop); - // zone line position - var pos = pi.pos + this.scrollerHeight/2; - // leap-frog zone position - var k = Math.floor(pos/Math.max(pi.height, this.scrollerHeight) + 1/2) + pi.no; - // which page number for page0 (even number pages)? - var p = (k % 2 === 0) ? k : k-1; - if (this.p0 != p && this.isPageInRange(p)) { - this.preserveDraggingRowNode(this.p0); - this.generatePage(p, this.$.page0); - this.positionPage(p, this.$.page0); - this.p0 = p; - updated = true; - this.p0RowBounds = this.getPageRowHeights(this.$.page0); - } - // which page number for page1 (odd number pages)? - p = (k % 2 === 0) ? Math.max(1, k-1) : k; - // position data page 1 - if (this.p1 != p && this.isPageInRange(p)) { - this.preserveDraggingRowNode(this.p1); - this.generatePage(p, this.$.page1); - this.positionPage(p, this.$.page1); - this.p1 = p; - updated = true; - this.p1RowBounds = this.getPageRowHeights(this.$.page1); - } - if (updated) { - // reset generator back to "full-list" values - this.$.generator.setRowOffset(0); - this.$.generator.setCount(this.count); - if (!this.fixedHeight) { - this.adjustBottomPage(); - this.adjustPortSize(); - } - } - }, - getPageRowHeights: function(page) { - var rows = {}; - var allDivs = page.hasNode().querySelectorAll("div[data-enyo-index]"); - for (var i=0, index, bounds; i < allDivs.length; i++) { - index = allDivs[i].getAttribute("data-enyo-index"); - if (index !== null) { - bounds = enyo.dom.getBounds(allDivs[i]); - rows[parseInt(index, 10)] = {height: bounds.height, width: bounds.width}; - } - } - return rows; - }, - updateRowBounds: function(index) { - if (this.p0RowBounds[index]) { - this.updateRowBoundsAtIndex(index, this.p0RowBounds, this.$.page0); - } - else if (this.p1RowBounds[index]) { - this.updateRowBoundsAtIndex(index, this.p1RowBounds, this.$.page1); - } - }, - updateRowBoundsAtIndex: function(index, rows, page) { - var rowDiv = page.hasNode().querySelector('div[data-enyo-index="' + index + '"]'); - var bounds = enyo.dom.getBounds(rowDiv); - rows[index].height = bounds.height; - rows[index].width = bounds.width; - }, - updateForPosition: function(inPos) { - this.update(this.calcPos(inPos)); - }, - calcPos: function(inPos) { - return (this.bottomUp ? (this.portSize - this.scrollerHeight - inPos) : inPos); - }, - adjustBottomPage: function() { - var bp = this.p0 >= this.p1 ? this.$.page0 : this.$.page1; - this.positionPage(bp.pageNo, bp); - }, - adjustPortSize: function() { - this.scrollerHeight = this.getBounds().height; - var s = Math.max(this.scrollerHeight, this.portSize); - this.$.port.applyStyle("height", s + "px"); - }, - positionPage: function(inPage, inTarget) { - inTarget.pageNo = inPage; - var y = this.pageToPosition(inPage); - inTarget.applyStyle(this.pageBound, y + "px"); - }, - pageToPosition: function(inPage) { - var y = 0; - var p = inPage; - while (p > 0) { - p--; - y += this.getPageHeight(p); - } - return y; - }, - positionToPageInfo: function(inY) { - var page = -1; - var p = this.calcPos(inY); - var h = this.defaultPageHeight; - while (p >= 0) { - page++; - h = this.getPageHeight(page); - p -= h; - } - page = Math.max(page, 0); - return { - no: page, - height: h, - pos: p + h, - startRow: (page * this.rowsPerPage), - endRow: Math.min((page + 1) * this.rowsPerPage - 1, this.count - 1) - }; - }, - isPageInRange: function(inPage) { - return inPage == Math.max(0, Math.min(this.pageCount-1, inPage)); - }, - getPageHeight: function(inPageNo) { - var height = this.pageHeights[inPageNo]; - // estimate the height based on how many rows are in this page - if (!height) { - var firstRow = this.rowsPerPage * inPageNo; - var numRows = Math.min(this.count - firstRow, this.rowsPerPage); - height = this.defaultPageHeight * (numRows / this.rowsPerPage); - } - // can never return height of 0, as that would lead to infinite loops - return Math.max(1, height); - }, - invalidatePages: function() { - this.p0 = this.p1 = null; - this.p0RowBounds = {}; - this.p1RowBounds = {}; - // clear the html in our render targets - this.$.page0.setContent(""); - this.$.page1.setContent(""); - }, - invalidateMetrics: function() { - this.pageHeights = []; - this.rowHeight = 0; - this.updateMetrics(); - }, - scroll: function(inSender, inEvent) { - var r = this.inherited(arguments); - var pos = this.getScrollTop(); - if (this.lastPos === pos) { - return r; - } - this.lastPos = pos; - this.update(pos); - if (this.pinnedReorderMode) { - this.reorderScroll(inSender, inEvent); - } - return r; - }, - setScrollTop: function(inScrollTop) { - this.update(inScrollTop); - this.inherited(arguments); - this.twiddle(); - }, - getScrollPosition: function() { - return this.calcPos(this.getScrollTop()); - }, - setScrollPosition: function(inPos) { - this.setScrollTop(this.calcPos(inPos)); - }, - //* @public - //* Scrolls the list so the last item is visible. - scrollToBottom: function() { - this.update(this.getScrollBounds().maxTop); - this.inherited(arguments); - }, - //* Scrolls to the specified row. - scrollToRow: function(inRow) { - var page = this.pageForRow(inRow); - var pageRow = inRow % this.rowsPerPage; - var h = this.pageToPosition(page); - // update the page - this.updateForPosition(h); - // call pageToPosition again and this time should return the right pos since the page info is populated - h = this.pageToPosition(page); - this.setScrollPosition(h); - if (page == this.p0 || page == this.p1) { - var rowNode = this.$.generator.fetchRowNode(inRow); - if (rowNode) { - // calc row offset - var offset = rowNode.offsetTop; - if (this.bottomUp) { - offset = this.getPageHeight(page) - rowNode.offsetHeight - offset; - } - var y = this.getScrollPosition() + offset; - this.setScrollPosition(y); - } - } - }, - //* Scrolls to the beginning of the list. - scrollToStart: function() { - this[this.bottomUp ? "scrollToBottom" : "scrollToTop"](); - }, - //* Scrolls to the end of the list. - scrollToEnd: function() { - this[this.bottomUp ? "scrollToTop" : "scrollToBottom"](); - }, - //* Re-renders the list at the current position. - refresh: function() { - this.invalidatePages(); - this.update(this.getScrollTop()); - this.stabilize(); - - //FIXME: Necessary evil for Android 4.0.4 refresh bug - if (enyo.platform.android === 4) { - this.twiddle(); - } - }, - /** - Re-renders the list from the beginning. This is used when changing the - data model for the list. This also clears the selection state. - */ - reset: function() { - this.getSelection().clear(); - this.invalidateMetrics(); - this.invalidatePages(); - this.stabilize(); - this.scrollToStart(); - }, - /** - Returns the [enyo.Selection](#enyo.Selection) component that - manages the selection state for this list. - */ - getSelection: function() { - return this.$.generator.getSelection(); - }, - /** - Sets the selection state for the given row index. - _inData_ is an optional data value stored in the selection object. - - Modifying selection will not automatically rerender the row, - so use [renderRow](#enyo.List::renderRow) or [refresh](#enyo.List::refresh) - to update the view. - */ - select: function(inIndex, inData) { - return this.getSelection().select(inIndex, inData); - }, - /** - Clears the selection state for the given row index. - - Modifying selection will not automatically re-render the row, - so use [renderRow](#enyo.List::renderRow) or [refresh](#enyo.List::refresh) - to update the view. - */ - deselect: function(inIndex) { - return this.getSelection().deselect(inIndex); - }, - //* Gets the selection state for the given row index. - isSelected: function(inIndex) { - return this.$.generator.isSelected(inIndex); - }, - /** - Re-renders the specified row. Call this method after making - modifications to a row, to force it to render. - */ - renderRow: function(inIndex) { - this.$.generator.renderRow(inIndex); - }, - //* Updates row bounds when rows are re-rendered. - rowRendered: function(inSender, inEvent) { - this.updateRowBounds(inEvent.rowIndex); - }, - //* Prepares the row to become interactive. - prepareRow: function(inIndex) { - this.$.generator.prepareRow(inIndex); - }, - //* Restores the row to being non-interactive. - lockRow: function() { - this.$.generator.lockRow(); - }, - /** - Performs a set of tasks by running the function _inFunc_ on a row (which - must be interactive at the time the tasks are performed). Locks the row - when done. - */ - performOnRow: function(inIndex, inFunc, inContext) { - this.$.generator.performOnRow(inIndex, inFunc, inContext); - }, - //* @protected - animateFinish: function(inSender) { - this.twiddle(); - return true; - }, - // FIXME: Android 4.04 has issues with nested composited elements; for example, a SwipeableItem, - // can incorrectly generate taps on its content when it has slid off the screen; - // we address this BUG here by forcing the Scroller to "twiddle" which corrects the bug by - // provoking a dom update. - twiddle: function() { - var s = this.getStrategy(); - enyo.call(s, "twiddle"); - }, - // return page0 or page1 control depending on pageNumber odd/even status - pageForPageNumber: function(pageNumber, checkRange) { - if (pageNumber % 2 === 0) { - return (!checkRange || (pageNumber === this.p0)) ? this.$.page0 : null; - } - else { - return (!checkRange || (pageNumber === this.p1)) ? this.$.page1 : null; - } - return null; - }, - /** - ---- Reorder functionality ------------ - */ - //* Determines whether we should handle the hold event as a reorder hold. - shouldStartReordering: function(inSender, inEvent) { - if(!this.getReorderable() || !(inEvent.rowIndex >= 0) || this.pinnedReorderMode || - inSender !== this.$.strategy || !(inEvent.index >= 0)) { - return false; - } - return true; - }, - //* Processes hold event and prepares for reordering. - startReordering: function(inEvent) { - // disable drag to scroll on strategy - this.$.strategy.listReordering = true; - - this.buildReorderContainer(); - this.doSetupReorderComponents(inEvent); - this.styleReorderContainer(inEvent); - - this.draggingRowIndex = this.placeholderRowIndex = inEvent.rowIndex; - this.draggingRowNode = inEvent.target; - this.removedInitialPage = false; - this.itemMoved = false; - this.initialPageNumber = this.currentPageNumber = this.pageForRow(inEvent.rowIndex); - this.prevScrollTop = this.getScrollTop(); - - // fill row being reordered with placeholder - this.replaceNodeWithPlaceholder(inEvent.rowIndex); - }, - /** - Fills reorder container with draggable reorder components defined by the - application. - */ - buildReorderContainer: function() { - this.$.reorderContainer.destroyClientControls(); - for(var i=0;i= this.placeholderRowIndex) { - this.movePlaceholderToIndex(Math.min(this.count, index + 1)); - } - else { - this.movePlaceholderToIndex(index); - } - } - }, - //* Positions the reorder node based on the dx and dy of the drag event. - positionReorderNode: function(e) { - var reorderNodeBounds = this.$.reorderContainer.getBounds(); - var left = reorderNodeBounds.left + e.ddx; - var top = reorderNodeBounds.top + e.ddy; - top = (this.getStrategyKind() == "ScrollStrategy") ? top + (this.getScrollTop() - this.prevScrollTop) : top; - this.$.reorderContainer.addStyles("top: "+top+"px ; left: "+left+"px"); - this.prevScrollTop = this.getScrollTop(); - }, - /** - Checks if the list should scroll when dragging and, if so, starts the - scroll timeout timer. Auto-scrolling happens when the user drags an item - within the top/bottom boundary percentage defined in - _this.dragToScrollThreshold_. - */ - checkForAutoScroll: function(inEvent) { - var position = enyo.dom.calcNodePosition(this.hasNode()); - var bounds = this.getBounds(); - var perc; - this.autoscrollPageY = inEvent.pageY; - if(inEvent.pageY - position.top < bounds.height * this.dragToScrollThreshold) { - perc = 100*(1 - ((inEvent.pageY - position.top) / (bounds.height * this.dragToScrollThreshold))); - this.scrollDistance = -1*perc; - } else if(inEvent.pageY - position.top > bounds.height * (1 - this.dragToScrollThreshold)) { - perc = 100*((inEvent.pageY - position.top - bounds.height*(1 - this.dragToScrollThreshold)) / (bounds.height - (bounds.height * (1 - this.dragToScrollThreshold)))); - this.scrollDistance = 1*perc; - } else { - this.scrollDistance = 0; - } - // stop scrolling if distance is zero (i.e., user isn't scrolling to the edges of - // the list); otherwise, start it if not already started - if (this.scrollDistance === 0) { - this.stopAutoScrolling(); - } else { - if(!this.autoScrollTimeout) { - this.startAutoScrolling(); - } - } - }, - //* Stops auto-scrolling. - stopAutoScrolling: function() { - if(this.autoScrollTimeout) { - clearTimeout(this.autoScrollTimeout); - this.autoScrollTimeout = null; - } - }, - //* Starts auto-scrolling. - startAutoScrolling: function() { - this.autoScrollTimeout = setInterval(enyo.bind(this, this.autoScroll), this.autoScrollTimeoutMS); - }, - //* Scrolls the list by the distance specified in _this.scrollDistance_. - autoScroll: function() { - if(this.scrollDistance === 0) { - this.stopAutoScrolling(); - } else { - if(!this.autoScrollTimeout) { - this.startAutoScrolling(); - } - } - this.setScrollPosition(this.getScrollPosition() + this.scrollDistance); - this.positionReorderNode({ddx: 0, ddy: 0}); - - // if the current index the user is dragging over has changed, move the placeholder - this.updatePlaceholderPosition(this.autoscrollPageY); - }, - /** - Moves the placeholder (i.e., the gap between rows) to the row currently - under the user's pointer. This provides a visual cue, showing the user - where the item being dragged will go if it is dropped. - */ - movePlaceholderToIndex: function(index) { - var node, nodeParent; - if (index < 0) { - return; - } - else if (index >= this.count) { - node = null; - nodeParent = this.pageForPageNumber(this.pageForRow(this.count - 1)).hasNode(); - } - else { - node = this.$.generator.fetchRowNode(index); - nodeParent = node.parentNode; - } - // figure next page for placeholder - var nextPageNumber = this.pageForRow(index); - - // don't add pages beyond the original page count - if(nextPageNumber >= this.pageCount) { - nextPageNumber = this.currentPageNumber; - } - - // move the placeholder to just after our "index" node - nodeParent.insertBefore( - this.placeholderNode, - node); - - if(this.currentPageNumber !== nextPageNumber) { - // if moving to different page, recalculate page heights and reposition pages - this.updatePageHeight(this.currentPageNumber); - this.updatePageHeight(nextPageNumber); - this.updatePagePositions(nextPageNumber); - } - - // save updated state - this.placeholderRowIndex = index; - this.currentPageNumber = nextPageNumber; - - // remember that we moved an item (to prevent pinning at the wrong time) - this.itemMoved = true; - }, - /** - Turns off reordering. If the user didn't drag the item being reordered - outside of its original position, goes into pinned reorder mode. - */ - finishReordering: function(inSender, inEvent) { - if(!this.isReordering() || this.pinnedReorderMode || this.completeReorderTimeout) { - return; - } - this.stopAutoScrolling(); - // enable drag-scrolling on strategy - this.$.strategy.listReordering = false; - // animate reorder container to proper position and then complete - // reordering actions - this.moveReorderedContainerToDroppedPosition(inEvent); - this.completeReorderTimeout = setTimeout( - enyo.bind(this, this.completeFinishReordering, inEvent), 100); - - inEvent.preventDefault(); - return true; - }, - //* - moveReorderedContainerToDroppedPosition: function() { - var offset = this.getRelativeOffset(this.placeholderNode, this.hasNode()); - var top = (this.getStrategyKind() == "ScrollStrategy") ? offset.top : offset.top - this.getScrollTop(); - var left = offset.left - this.getScrollLeft(); - this.positionReorderContainer(left,top); - }, - /** - After the reordered item has been animated to its position, completes - the reordering logic. - */ - completeFinishReordering: function(inEvent) { - this.completeReorderTimeout = null; - // adjust placeholderRowIndex to now be the final resting place - if (this.placeholderRowIndex > this.draggingRowIndex) { - this.placeholderRowIndex = Math.max(0, this.placeholderRowIndex - 1); - } - // if the user dropped the item in the same location where it was picked up, and they - // didn't move any other items in the process, pin the item and go into pinned reorder mode - if(this.draggingRowIndex == this.placeholderRowIndex && - this.pinnedReorderComponents.length && !this.pinnedReorderMode && !this.itemMoved) { - this.beginPinnedReorder(inEvent); - return; - } - this.removeDraggingRowNode(); - this.removePlaceholderNode(); - this.emptyAndHideReorderContainer(); - // clear this early to prevent scroller code from using disappeared placeholder - this.pinnedReorderMode = false; - this.reorderRows(inEvent); - this.draggingRowIndex = this.placeholderRowIndex = -1; - this.refresh(); - }, - //* Go into pinned reorder mode - beginPinnedReorder: function(e) { - this.buildPinnedReorderContainer(); - this.doSetupPinnedReorderComponents(enyo.mixin(e, {index: this.draggingRowIndex})); - this.pinnedReorderMode = true; - this.initialPinPosition = e.pageY; - }, - //* Clears contents of reorder container, then hides. - emptyAndHideReorderContainer: function() { - this.$.reorderContainer.destroyComponents(); - this.$.reorderContainer.setShowing(false); - }, - //* Fills reorder container with pinned controls. - buildPinnedReorderContainer: function() { - this.$.reorderContainer.destroyClientControls(); - for(var i=0;i 0) ? 1 : -1; - var node, i, newIndex, currentIndex; - - if(direction === 1) { - node = this.$.generator.fetchRowNode(this.draggingRowIndex); - if (node) { - node.setAttribute("data-enyo-index", "reordered"); - } - for(i=(to-1),newIndex=to;i>=from;i--) { - node = this.$.generator.fetchRowNode(i); - if(!node) { - continue; - } - currentIndex = parseInt(node.getAttribute("data-enyo-index"), 10); - newIndex = currentIndex + 1; - node.setAttribute("data-enyo-index", newIndex); - } - node = this.hasNode().querySelector('[data-enyo-index="reordered"]'); - node.setAttribute("data-enyo-index", this.placeholderRowIndex); - - } else { - node = this.$.generator.fetchRowNode(this.draggingRowIndex); - if (node) { - node.setAttribute("data-enyo-index", this.placeholderRowIndex); - } - for(i=(from+1), newIndex=from;i<=to;i++) { - node = this.$.generator.fetchRowNode(i); - if(!node) { - continue; - } - currentIndex = parseInt(node.getAttribute("data-enyo-index"), 10); - newIndex = currentIndex - 1; - node.setAttribute("data-enyo-index", newIndex); - } - } - }, - //* Determines if an item was reordered far enough that it warrants a refresh. - shouldDoRefresh: function() { - return (Math.abs(this.initialPageNumber - this.currentPageNumber) > 1); - }, - //* Gets node height, width, top, and left values. - getNodeStyle: function(index) { - var node = this.$.generator.fetchRowNode(index); - if(!node) { - return; - } - var offset = this.getRelativeOffset(node, this.hasNode()); - var dimensions = enyo.dom.getBounds(node); - return {h: dimensions.height, w: dimensions.width, left: offset.left, top: offset.top}; - }, - //* Gets offset relative to a positioned ancestor node. - getRelativeOffset: function (n, p) { - var ro = {top: 0, left: 0}; - if (n !== p && n.parentNode) { - do { - ro.top += n.offsetTop || 0; - ro.left += n.offsetLeft || 0; - n = n.offsetParent; - } while (n && n !== p); - } - return ro; - }, - replaceNodeWithPlaceholder: function(index) { - var node = this.$.generator.fetchRowNode(index); - if(!node) { - enyo.log("No node - "+index); - return; - } - // create and style placeholder node - this.placeholderNode = this.createPlaceholderNode(node); - // hide existing node - this.hiddenNode = this.hideNode(node); - // insert placeholder node where original node was - var currentPage = this.pageForPageNumber(this.currentPageNumber); - currentPage.hasNode().insertBefore(this.placeholderNode,this.hiddenNode); - }, - /** - Creates and returns a placeholder node with dimensions matching those of - the passed-in node. - */ - createPlaceholderNode: function(node) { - var placeholderNode = this.$.placeholder.hasNode().cloneNode(true); - var nodeDimensions = enyo.dom.getBounds(node); - placeholderNode.style.height = nodeDimensions.height + "px"; - placeholderNode.style.width = nodeDimensions.width + "px"; - return placeholderNode; - }, - //* Removes the placeholder node from the DOM. - removePlaceholderNode: function() { - this.removeNode(this.placeholderNode); - this.placeholderNode = null; - }, - removeDraggingRowNode: function() { - this.draggingRowNode = null; - var holdingArea = this.$.holdingarea.hasNode(); - holdingArea.innerHTML = ""; - }, - //* Removes the passed-in node from the DOM. - removeNode: function(node) { - if(!node || !node.parentNode) { - return; - } - node.parentNode.removeChild(node); - }, - /** - Updates _this.pageHeights_ to support the placeholder node's jumping - from one page to the next. - */ - updatePageHeight: function(pageNumber) { - if (pageNumber < 0) { - return; - } - var pageControl = this.pageForPageNumber(pageNumber, true); - if (pageControl) { - var h0 = this.pageHeights[pageNumber]; - var pageHeight = Math.max(1, pageControl.getBounds().height); - this.pageHeights[pageNumber] = pageHeight; - this.portSize += pageHeight - h0; - } - }, - /** - Repositions the two passed-in pages to support the placeholder node's - jumping from one page to the next. - */ - updatePagePositions: function(nextPageNumber) { - this.positionPage(this.currentPageNumber, this.pageForPageNumber(this.currentPageNumber)); - this.positionPage(nextPageNumber, this.pageForPageNumber(nextPageNumber)); - }, - //* Corrects page heights array after reorder is complete. - correctPageHeights: function() { - this.updatePageHeight(this.currentPageNumber); - if (this.initialPageNumber != this.currentPageNumber) { - this.updatePageHeight(this.initialPageNumber); - } - }, - hideNode: function(node) { - node.style.display = "none"; - return node; - }, - showNode: function(node) { - node.style.display = "block"; - return node; - }, - //* @public - //* Called by client code to finalize a pinned mode reordering, such as when the "Drop" button is pressed - //* on the pinned placeholder row. - dropPinnedRow: function(inEvent) { - // animate reorder container to proper position and then complete reording actions - this.moveReorderedContainerToDroppedPosition(inEvent); - this.completeReorderTimeout = setTimeout( - enyo.bind(this, this.completeFinishReordering, inEvent), 100); - return; - }, - cancelPinnedMode: function(inEvent) { - // make it look like we're dropping in original location - this.placeholderRowIndex = this.draggingRowIndex; - this.dropPinnedRow(inEvent); - }, - //* @protected - //* Returns the row index that is under the given position on the page. If the - //* position is off the end of the list, this will return this.count. If the position - //* is before the start of the list, you'll get -1. - getRowIndexFromCoordinate: function(y) { - var cursorPosition = this.getScrollTop() + y - enyo.dom.calcNodePosition(this.hasNode()).top; - // happens if we try to drag past top of list - if (cursorPosition < 0) { - return -1; - } - var pageInfo = this.positionToPageInfo(cursorPosition); - var rows = (pageInfo.no == this.p0) ? this.p0RowBounds : this.p1RowBounds; - // might have only rendered one page, so catch that here - if (!rows) { - return this.count; - } - var posOnPage = pageInfo.pos; - var placeholderHeight = this.placeholderNode ? enyo.dom.getBounds(this.placeholderNode).height : 0; - var totalHeight = 0; - for(var i=pageInfo.startRow; i <= pageInfo.endRow; ++i) { - // do extra check for row that has placeholder as we'll return -1 here for no match - if (i === this.placeholderRowIndex) { - // for placeholder - totalHeight += placeholderHeight; - if(totalHeight >= posOnPage) { - return -1; - } - } - // originally dragged row is hidden, so don't count it - if (i !== this.draggingRowIndex) { - totalHeight += rows[i].height; - if(totalHeight >= posOnPage) { - return i; - } - } - } - return i; - }, - //* Gets the position of a node (identified via index) on the page. - getIndexPosition: function(index) { - return enyo.dom.calcNodePosition(this.$.generator.fetchRowNode(index)); - }, - //* Sets _$item_'s position to match that of the list row at _index_. - setItemPosition: function($item,index) { - var clonedNodeStyle = this.getNodeStyle(index); - var top = (this.getStrategyKind() == "ScrollStrategy") ? clonedNodeStyle.top : clonedNodeStyle.top - this.getScrollTop(); - var styleStr = "top:"+top+"px; left:"+clonedNodeStyle.left+"px;"; - $item.addStyles(styleStr); - }, - //* Sets _$item_'s width and height to match those of the list row at _index_. - setItemBounds: function($item,index) { - var clonedNodeStyle = this.getNodeStyle(index); - var styleStr = "width:"+clonedNodeStyle.w+"px; height:"+clonedNodeStyle.h+"px;"; - $item.addStyles(styleStr); - }, - /** - When in pinned reorder mode, repositions the pinned placeholder when the - user has scrolled far enough. - */ - reorderScroll: function(inSender, e) { - // if we are using the standard scroll strategy, we have to move the pinned row with the scrolling - if(this.getStrategyKind() == "ScrollStrategy") { - this.$.reorderContainer.addStyles("top:"+(this.initialPinPosition+this.getScrollTop()-this.rowHeight)+"px;"); - } - // y coordinate on screen of the pinned item doesn't change as we scroll things - this.updatePlaceholderPosition(this.initialPinPosition); - }, - hideReorderingRow: function() { - var hiddenNode = this.hasNode().querySelector('[data-enyo-index="'+this.draggingRowIndex+'"]'); - // hide existing node - if(hiddenNode) { - this.hiddenNode = this.hideNode(hiddenNode); - } - }, - isReordering: function() { - return (this.draggingRowIndex > -1); - }, - - /** - ---- Swipeable functionality ------------ - */ - - isSwiping: function() { - // we're swiping when the index is set and we're not in the middle of completing or backing out a swipe - return (this.swipeIndex != null && !this.swipeComplete && this.swipeDirection != null); - }, - /** - When a drag starts, gets the direction of the drag as well as the index - of the item being dragged, and resets any pertinent values. Then kicks - off the swipe sequence. - */ - swipeDragStart: function(inSender, inEvent) { - // if we're not on a row or the swipe is vertical or if we're in the middle of reordering, just say no - if(inEvent.index == null || inEvent.vertical) { - return true; - } - - // if we are waiting to complete a swipe, complete it - if(this.completeSwipeTimeout) { - this.completeSwipe(inEvent); - } - - // reset swipe complete flag - this.swipeComplete = false; - - if (this.swipeIndex != inEvent.index) { - this.clearSwipeables(); - this.swipeIndex = inEvent.index; - } - this.swipeDirection = inEvent.xDirection; - - // start swipe sequence only if we are not currently showing a persistent item - if(!this.persistentItemVisible) { - this.startSwipe(inEvent); - } - - // reset dragged distance (for dragfinish) - this.draggedXDistance = 0; - this.draggedYDistance = 0; - - return true; - }, - /** - When a drag is in progress, updates the position of the swipeable - container based on the ddx of the event. - */ - swipeDrag: function(inSender, inEvent) { - // if a persistent swipeableItem is still showing, handle it separately - if (this.persistentItemVisible) { - this.dragPersistentItem(inEvent); - return this.preventDragPropagation; - } - // early exit if there's no matching dragStart to set item - if (!this.isSwiping()) { - return false; - } - // apply new position - this.dragSwipeableComponents(this.calcNewDragPosition(inEvent.ddx)); - // save dragged distance (for dragfinish) - this.draggedXDistance = inEvent.dx; - this.draggedYDistance = inEvent.dy; - return true; - }, - /* - When the current drag completes, decides whether to complete the swipe - based on how far the user pulled the swipeable container. - */ - swipeDragFinish: function(inSender, inEvent) { - // if a persistent swipeableItem is still showing, complete drag away or bounce - if (this.persistentItemVisible) { - this.dragFinishPersistentItem(inEvent); - // early exit if there's no matching dragStart to set item - } else if (!this.isSwiping()) { - return false; - // otherwise if user dragged more than 20% of the width, complete the swipe. if not, back out. - } else { - var percentageDragged = this.calcPercentageDragged(this.draggedXDistance); - if ((percentageDragged > this.percentageDraggedThreshold) && (inEvent.xDirection === this.swipeDirection)) { - this.swipe(this.fastSwipeSpeedMS); - } else { - this.backOutSwipe(inEvent); - } - } - - return this.preventDragPropagation; - }, - // reorder takes precedence over swipes, and not having it turned on or swipeable controls defined also disables this - isSwipeable: function() { - return this.enableSwipe && this.$.swipeableComponents.controls.length !== 0 && - !this.isReordering() && !this.pinnedReorderMode; - }, - // Positions the swipeable components block at the current row. - positionSwipeableContainer: function(index,xDirection) { - var node = this.$.generator.fetchRowNode(index); - if(!node) { - return; - } - var offset = this.getRelativeOffset(node, this.hasNode()); - var dimensions = enyo.dom.getBounds(node); - var x = (xDirection == 1) ? -1*dimensions.width : dimensions.width; - this.$.swipeableComponents.addStyles("top: "+offset.top+"px; left: "+x+"px; height: "+dimensions.height+"px; width: "+dimensions.width+"px;"); - }, - /** - Calculates new position for the swipeable container based on the user's - drag action. Don't allow the container to drag beyond either edge. - */ - calcNewDragPosition: function(dx) { - var parentBounds = this.$.swipeableComponents.getBounds(); - var xPos = parentBounds.left; - var dimensions = this.$.swipeableComponents.getBounds(); - var xlimit = (this.swipeDirection == 1) ? 0 : -1*dimensions.width; - var x = (this.swipeDirection == 1) - ? (xPos + dx > xlimit) - ? xlimit - : xPos + dx - : (xPos + dx < xlimit) - ? xlimit - : xPos + dx; - return x; - }, - dragSwipeableComponents: function(x) { - this.$.swipeableComponents.applyStyle("left",x+"px"); - }, - /** - Begins swiping sequence by positioning the swipeable container and - bubbling the setupSwipeItem event. - */ - startSwipe: function(e) { - // modify event index to always have this swipeItem value - e.index = this.swipeIndex; - this.positionSwipeableContainer(this.swipeIndex,e.xDirection); - this.$.swipeableComponents.setShowing(true); - this.setPersistentItemOrigin(e.xDirection); - this.doSetupSwipeItem(e); - }, - // If a persistent swipeableItem is still showing, drags it away or bounces it. - dragPersistentItem: function(e) { - var xPos = 0; - var x = (this.persistentItemOrigin == "right") - ? Math.max(xPos, (xPos + e.dx)) - : Math.min(xPos, (xPos + e.dx)); - this.$.swipeableComponents.applyStyle("left",x+"px"); - }, - // If a persistent swipeableItem is still showing, completes drag away or bounce. - dragFinishPersistentItem: function(e) { - var completeSwipe = (this.calcPercentageDragged(e.dx) > 0.2); - var dir = (e.dx > 0) ? "right" : (e.dx < 0) ? "left" : null; - if(this.persistentItemOrigin == dir) { - if(completeSwipe) { - this.slideAwayItem(); - } else { - this.bounceItem(e); - } - } else { - this.bounceItem(e); - } - }, - setPersistentItemOrigin: function(xDirection) { - this.persistentItemOrigin = xDirection == 1 ? "left" : "right"; - }, - calcPercentageDragged: function(dx) { - return Math.abs(dx/this.$.swipeableComponents.getBounds().width); - }, - swipe: function(speed) { - this.swipeComplete = true; - this.animateSwipe(0,speed); - }, - backOutSwipe: function(e) { - var dimensions = this.$.swipeableComponents.getBounds(); - var x = (this.swipeDirection == 1) ? -1*dimensions.width : dimensions.width; - this.animateSwipe(x,this.fastSwipeSpeedMS); - this.swipeDirection = null; - }, - bounceItem: function(e) { - var bounds = this.$.swipeableComponents.getBounds(); - if(bounds.left != bounds.width) { - this.animateSwipe(0,this.normalSwipeSpeedMS); - } - }, - slideAwayItem: function() { - var $item = this.$.swipeableComponents; - var parentWidth = $item.getBounds().width; - var xPos = (this.persistentItemOrigin == "left") ? -1*parentWidth : parentWidth; - this.animateSwipe(xPos,this.normalSwipeSpeedMS); - this.persistentItemVisible = false; - this.setPersistSwipeableItem(false); - }, - clearSwipeables: function() { - this.$.swipeableComponents.setShowing(false); - this.persistentItemVisible = false; - this.setPersistSwipeableItem(false); - }, - // Completes swipe and hides active swipeable item. - completeSwipe: function(e) { - if(this.completeSwipeTimeout) { - clearTimeout(this.completeSwipeTimeout); - this.completeSwipeTimeout = null; - } - // if this wasn't a persistent item, hide it upon completion and send swipe complete event - if(!this.getPersistSwipeableItem()) { - this.$.swipeableComponents.setShowing(false); - // if the swipe was completed, update the current row and bubble swipeComplete event - if(this.swipeComplete) { - this.doSwipeComplete({index: this.swipeIndex, xDirection: this.swipeDirection}); - } - } else { - this.persistentItemVisible = true; - } - this.swipeIndex = null; - this.swipeDirection = null; - }, - animateSwipe: function(targetX,totalTimeMS) { - var t0 = enyo.now(), t = 0; - var $item = this.$.swipeableComponents; - var origX = parseInt($item.domStyles.left,10); - var xDelta = targetX - origX; - - this.stopAnimateSwipe(); - - var fn = enyo.bind(this, function() { - var t = enyo.now() - t0; - var percTimeElapsed = t/totalTimeMS; - var currentX = origX + (xDelta)*Math.min(percTimeElapsed,1); - - // set new left - $item.applyStyle("left",currentX+"px"); - - // schedule next frame - this.job = enyo.requestAnimationFrame(fn); - - // potentially override animation TODO - - // go until we've hit our total time - if(t/totalTimeMS >= 1) { - this.stopAnimateSwipe(); - this.completeSwipeTimeout = setTimeout(enyo.bind(this, function() { - this.completeSwipe(); - }), this.completeSwipeDelayMS); - } - }); - - this.job = enyo.requestAnimationFrame(fn); - }, - stopAnimateSwipe: function() { - if(this.job) { - this.job = enyo.cancelRequestAnimationFrame(this.job); - } - } -}); \ No newline at end of file diff --git a/lib/layout/list/source/PulldownList.css b/lib/layout/list/source/PulldownList.css deleted file mode 100644 index 89f6da0..0000000 --- a/lib/layout/list/source/PulldownList.css +++ /dev/null @@ -1,60 +0,0 @@ -.enyo-list-pulldown { - position: absolute; - bottom: 100%; - left: 0; - right: 0; -} - -.enyo-puller { - position: relative; - height: 50px; - font-size: 22px; - color: #444; - padding: 20px 0 0px 34px; -} - -.enyo-puller-text { - position: absolute; - left: 80px; - top: 22px; -} - -.enyo-puller-arrow { - position: relative; - background: #444; - width: 7px; - height: 28px; - transition: transform 0.3s; - -webkit-transition: -webkit-transform 0.3s; - -moz-transition: -moz-transform 0.3s; - -o-transition: -o-transform 0.3s; - -ms-transition: -ms-transform 0.3s; -} - -.enyo-puller-arrow:after { - content: " "; - height: 0; - width: 0; - position: absolute; - border: 10px solid transparent; - border-bottom-color: #444; - bottom: 100%; - left: 50%; - margin-left: -10px; -} - -.enyo-puller-arrow-up { - transform: rotate(0deg); - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -ms-transform: rotate(0deg); -} - -.enyo-puller-arrow-down { - transform: rotate(180deg); - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -o-transform: rotate(180deg); - -ms-transform: rotate(180deg); -} \ No newline at end of file diff --git a/lib/layout/list/source/PulldownList.js b/lib/layout/list/source/PulldownList.js deleted file mode 100644 index 88e13c4..0000000 --- a/lib/layout/list/source/PulldownList.js +++ /dev/null @@ -1,202 +0,0 @@ -/** -_enyo.PulldownList_ is a list that provides a pull-to-refresh feature, which -allows new data to be retrieved and updated in the list. - -PulldownList provides the _onPullRelease_ event to allow an application to start -retrieving new data. The _onPullComplete_ event indicates that the pull is -complete and it's time to update the list with the new data. - - {name: "list", kind: "PulldownList", onSetupItem: "setupItem", - onPullRelease: "pullRelease", onPullComplete: "pullComplete", - components: [ - {name: "item"} - ]} - - pullRelease: function() { - this.search(); - }, - processSearchResults: function(inRequest, inResponse) { - this.results = inResponse.results; - this.$.list.setCount(this.results.length); - this.$.list.completePull(); - }, - pullComplete: function() { - this.$.list.reset(); - } -*/ -enyo.kind({ - name: "enyo.PulldownList", - kind: "List", - //* @protected - // Sets touch to true in inherited Scroller kind for touch-based scrolling strategy - touch: true, - // The pull notification area at the top of the list - pully: null, - pulldownTools: [ - {name: "pulldown", classes: "enyo-list-pulldown", components: [ - {name: "puller", kind: "Puller"} - ]} - ], - events: { - //* Fires when user initiates a pull action. - onPullStart: "", - //* Fires when user cancels a pull action. - onPullCancel: "", - //* Fires while a pull action is in progress. - onPull: "", - //* Fires when the list is released following a pull action, indicating - //* that we are ready to retrieve data. - onPullRelease: "", - //* Fires when data retrieval is complete, indicating that the data is - //* is ready to be displayed. - onPullComplete: "" - }, - handlers: { - onScrollStart: "scrollStartHandler", - onScrollStop: "scrollStopHandler", - ondragfinish: "dragfinish" - }, - //* Message displayed when list is not being pulled - pullingMessage: "Pull down to refresh...", - //* Message displayed while a pull action is in progress - pulledMessage: "Release to refresh...", - //* Message displayed while data is being retrieved - loadingMessage: "Loading...", - // - pullingIconClass: "enyo-puller-arrow enyo-puller-arrow-down", - pulledIconClass: "enyo-puller-arrow enyo-puller-arrow-up", - loadingIconClass: "", - //* @protected - create: function() { - var p = {kind: "Puller", showing: false, text: this.loadingMessage, iconClass: this.loadingIconClass, onCreate: "setPully"}; - this.listTools.splice(0, 0, p); - this.inherited(arguments); - this.setPulling(); - }, - initComponents: function() { - this.createChrome(this.pulldownTools); - this.accel = enyo.dom.canAccelerate(); - this.translation = this.accel ? "translate3d" : "translate"; - this.strategyKind = this.resetStrategyKind(); - this.inherited(arguments); - }, - // Temporarily use TouchScrollStrategy on iOS devices (see ENYO-1714) - resetStrategyKind: function() { - return (enyo.platform.android >= 3) - ? "TranslateScrollStrategy" - : "TouchScrollStrategy"; - }, - setPully: function(inSender, inEvent) { - this.pully = inEvent.originator; - }, - scrollStartHandler: function() { - this.firedPullStart = false; - this.firedPull = false; - this.firedPullCancel = false; - }, - scroll: function(inSender, inEvent) { - var r = this.inherited(arguments); - if (this.completingPull) { - this.pully.setShowing(false); - } - var s = this.getStrategy().$.scrollMath || this.getStrategy(); - var over = -1*this.getScrollTop(); - if (s.isInOverScroll() && over > 0) { - enyo.dom.transformValue(this.$.pulldown, this.translation, "0," + over + "px" + (this.accel ? ",0" : "")); - if (!this.firedPullStart) { - this.firedPullStart = true; - this.pullStart(); - this.pullHeight = this.$.pulldown.getBounds().height; - } - if (over > this.pullHeight && !this.firedPull) { - this.firedPull = true; - this.firedPullCancel = false; - this.pull(); - } - if (this.firedPull && !this.firedPullCancel && over < this.pullHeight) { - this.firedPullCancel = true; - this.firedPull = false; - this.pullCancel(); - } - } - return r; - }, - scrollStopHandler: function() { - if (this.completingPull) { - this.completingPull = false; - this.doPullComplete(); - } - }, - dragfinish: function() { - if (this.firedPull) { - var s = this.getStrategy().$.scrollMath || this.getStrategy(); - s.setScrollY(-1*this.getScrollTop() - this.pullHeight); - this.pullRelease(); - } - }, - //* @public - //* Signals that the list should execute pull completion. This is usually - //* called after the application has received the new data. - completePull: function() { - this.completingPull = true; - var s = this.getStrategy().$.scrollMath || this.getStrategy(); - s.setScrollY(this.pullHeight); - s.start(); - }, - //* @protected - pullStart: function() { - this.setPulling(); - this.pully.setShowing(false); - this.$.puller.setShowing(true); - this.doPullStart(); - }, - pull: function() { - this.setPulled(); - this.doPull(); - }, - pullCancel: function() { - this.setPulling(); - this.doPullCancel(); - }, - pullRelease: function() { - this.$.puller.setShowing(false); - this.pully.setShowing(true); - this.doPullRelease(); - }, - setPulling: function() { - this.$.puller.setText(this.pullingMessage); - this.$.puller.setIconClass(this.pullingIconClass); - }, - setPulled: function() { - this.$.puller.setText(this.pulledMessage); - this.$.puller.setIconClass(this.pulledIconClass); - } -}); - -enyo.kind({ - name: "enyo.Puller", - classes: "enyo-puller", - published: { - text: "", - iconClass: "" - }, - events: { - onCreate: "" - }, - components: [ - {name: "icon"}, - {name: "text", tag: "span", classes: "enyo-puller-text"} - ], - create: function() { - this.inherited(arguments); - this.doCreate(); - this.textChanged(); - this.iconClassChanged(); - }, - textChanged: function() { - this.$.text.setContent(this.text); - }, - iconClassChanged: function() { - this.$.icon.setClasses(this.iconClass); - } -}); \ No newline at end of file diff --git a/lib/layout/list/source/package.js b/lib/layout/list/source/package.js deleted file mode 100644 index b00e27f..0000000 --- a/lib/layout/list/source/package.js +++ /dev/null @@ -1,8 +0,0 @@ -enyo.depends( - "FlyweightRepeater.js", - "List.css", - "List.js", - "PulldownList.css", - "PulldownList.js", - "AroundList.js" -); \ No newline at end of file diff --git a/lib/layout/list/source/wip-package.js b/lib/layout/list/source/wip-package.js deleted file mode 100644 index bafc093..0000000 --- a/lib/layout/list/source/wip-package.js +++ /dev/null @@ -1,6 +0,0 @@ -enyo.depends( - // Add wip controls here - "AlphaJumper.css", - "AlphaJumper.js", - "AlphaJumpList.js" -); \ No newline at end of file diff --git a/lib/layout/package.js b/lib/layout/package.js deleted file mode 100644 index a796319..0000000 --- a/lib/layout/package.js +++ /dev/null @@ -1,8 +0,0 @@ -enyo.depends( - "fittable", - "list", - "slideable", - "panels", - "tree", - "imageview" -); diff --git a/lib/layout/panels/package.js b/lib/layout/panels/package.js deleted file mode 100644 index f1de4f2..0000000 --- a/lib/layout/panels/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "source/" -); \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.css b/lib/layout/panels/samples/PanelsFlickrSample.css deleted file mode 100644 index 8855c8e..0000000 --- a/lib/layout/panels/samples/PanelsFlickrSample.css +++ /dev/null @@ -1,72 +0,0 @@ -.panels-sample-flickr-panels { - color: white; - background: #555; -} -.panels-sample-flickr-panels > * { - width: 320px; - box-shadow: -4px 0px 4px rgba(0,0,0,0.3); - -moz-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); - -webkit-box-shadow: -4px 0px 4px rgba(0,0,0,0.3); -} -.panels-sample-flickr-item { - position: relative; - border-bottom: 1px solid #0E0E0E; - padding: 12px 16px; - background-color: #333333; -} - -.panels-sample-flickr-item.onyx-selected { - background-color: MidnightBlue; -} - -.panels-sample-flickr-title { - position: absolute; - top: 40px; - right: 0; - left: 100px; - - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -.panels-sample-flickr-thumbnail { - width: 75px; - height: 75px; -} -.panels-sample-flickr-more-button { - color: white; margin: 10px; -} -.panels-sample-flickr-more-spinner { - vertical-align: middle; - margin: -4px 0 0 4px; -} -.panels-sample-flickr-center { - margin: auto; -} -.panels-sample-flickr-main { - background-color: #333; -} -.panels-sample-flickr-image { - box-sizing: border-box; - max-height: 90%; - max-width: 90%; - border: solid 5px #CCC; - box-shadow: 1px 1px 5px #999; - width: auto; - height: auto; -} - -.panels-sample-flickr-image.wide { - width: 100%; -} - - -@media all and (max-width: 800px) { - .panels-sample-flickr-image.wide { - width: auto; - } -} - -.panels-sample-flickr-image.tall { - height: 100%; -} \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.html b/lib/layout/panels/samples/PanelsFlickrSample.html deleted file mode 100644 index 5e0be21..0000000 --- a/lib/layout/panels/samples/PanelsFlickrSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Panels Flickr App Example - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsFlickrSample.js b/lib/layout/panels/samples/PanelsFlickrSample.js deleted file mode 100644 index b4177df..0000000 --- a/lib/layout/panels/samples/PanelsFlickrSample.js +++ /dev/null @@ -1,152 +0,0 @@ -enyo.kind({ - name: "enyo.sample.PanelsFlickrSample", - kind: "Panels", - classes: "panels-sample-flickr-panels enyo-unselectable enyo-fit", - arrangerKind: "CollapsingArranger", - components: [ - {layoutKind: "FittableRowsLayout", components: [ - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.InputDecorator", style: "width: 90%;", layoutKind: "FittableColumnsLayout", components: [ - {name: "searchInput", fit: true, kind: "onyx.Input", value: "Japan", onchange: "search"}, - {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px; height: 20px;"} - ]}, - {name: "searchSpinner", kind: "Image", src: "assets/spinner.gif", showing: false} - ]}, - {kind: "List", fit: true, touch: true, onSetupItem: "setupItem", components: [ - {name: "item", style: "padding: 10px;", classes: "panels-sample-flickr-item enyo-border-box", ontap: "itemTap", components: [ - {name: "thumbnail", kind: "Image", classes: "panels-sample-flickr-thumbnail"}, - {name: "title", classes: "panels-sample-flickr-title"} - ]}, - {name: "more", style: "background-color: #323232;", components: [ - {kind: "onyx.Button", content: "more photos", classes: "onyx-dark panels-sample-flickr-more-button", ontap: "more"}, - {name: "moreSpinner", kind: "Image", src: "assets/spinner.gif", classes: "panels-sample-flickr-more-spinner"} - ]} - ]} - ]}, - {name: "pictureView", fit: true, kind: "FittableRows", classes: "enyo-fit panels-sample-flickr-main", components: [ - {name: "backToolbar", kind: "onyx.Toolbar", showing: false, components: [ - {kind: "onyx.Button", content: "Back", ontap: "showList"} - ]}, - {fit: true, style: "position: relative;", components: [ - {name: "flickrImage", kind: "Image", classes: "enyo-fit panels-sample-flickr-center panels-sample-flickr-image", showing: false, onload: "imageLoaded", onerror: "imageLoaded"}, - {name: "imageSpinner", kind: "Image", src: "assets/spinner-large.gif", classes: "enyo-fit panels-sample-flickr-center", showing: false} - ]} - ]}, - {kind: "FlickrSearch", onResults: "searchResults"} - ], - rendered: function() { - this.inherited(arguments); - this.search(); - }, - reflow: function() { - this.inherited(arguments); - var backShowing = this.$.backToolbar.showing; - this.$.backToolbar.setShowing(enyo.Panels.isScreenNarrow()); - if (this.$.backToolbar.showing != backShowing) { - this.$.pictureView.resized(); - } - }, - search: function() { - this.searchText = this.$.searchInput.getValue(); - this.page = 0; - this.results = []; - this.$.searchSpinner.show(); - this.$.flickrSearch.search(this.searchText); - }, - searchResults: function(inSender, inResults) { - this.$.searchSpinner.hide(); - this.$.moreSpinner.hide(); - this.results = this.results.concat(inResults); - this.$.list.setCount(this.results.length); - if (this.page === 0) { - this.$.list.reset(); - } else { - this.$.list.refresh(); - } - }, - setupItem: function(inSender, inEvent) { - var i = inEvent.index; - var item = this.results[i]; - this.$.item.addRemoveClass("onyx-selected", inSender.isSelected(inEvent.index)); - this.$.thumbnail.setSrc(item.thumbnail); - this.$.title.setContent(item.title || "Untitled"); - this.$.more.canGenerate = !this.results[i+1]; - }, - more: function() { - this.page++; - this.$.moreSpinner.show(); - this.$.flickrSearch.search(this.searchText, this.page); - }, - itemTap: function(inSender, inEvent) { - if (enyo.Panels.isScreenNarrow()) { - this.setIndex(1); - } - this.$.imageSpinner.show(); - var item = this.results[inEvent.index]; - - if (item.original == this.$.flickrImage.getSrc()) { - this.imageLoaded(); - } else { - this.$.flickrImage.hide(); - this.$.flickrImage.setSrc(item.original); - } - }, - imageLoaded: function() { - var img = this.$.flickrImage; - img.removeClass("tall"); - img.removeClass("wide"); - img.show(); - var b = img.getBounds(); - var r = b.height / b.width; - if (r >= 1.25) { - img.addClass("tall"); - } else if (r <= 0.8 ) { - img.addClass("wide"); - } - this.$.imageSpinner.hide(); - }, - showList: function() { - this.setIndex(0); - } -}); - -// A simple component to do a Flickr search. -enyo.kind({ - name: "FlickrSearch", - kind: "Component", - published: { - searchText: "" - }, - events: { - onResults: "" - }, - url: "http://api.flickr.com/services/rest/", - pageSize: 200, - api_key: "2a21b46e58d207e4888e1ece0cb149a5", - search: function(inSearchText, inPage) { - this.searchText = inSearchText || this.searchText; - var i = (inPage || 0) * this.pageSize; - var params = { - method: "flickr.photos.search", - format: "json", - api_key: this.api_key, - per_page: this.pageSize, - page: i, - text: this.searchText - }; - return new enyo.JsonpRequest({url: this.url, callbackName: "jsoncallback"}) - .response(this, "processResponse") - .go(params) - ; - }, - processResponse: function(inSender, inResponse) { - var photos = inResponse.photos ? inResponse.photos.photo || [] : []; - for (var i=0, p; (p=photos[i]); i++) { - var urlprefix = "http://farm" + p.farm + ".static.flickr.com/" + p.server + "/" + p.id + "_" + p.secret; - p.thumbnail = urlprefix + "_s.jpg"; - p.original = urlprefix + ".jpg"; - } - this.doResults(photos); - return photos; - } -}); diff --git a/lib/layout/panels/samples/PanelsSample.css b/lib/layout/panels/samples/PanelsSample.css deleted file mode 100644 index fed08d2..0000000 --- a/lib/layout/panels/samples/PanelsSample.css +++ /dev/null @@ -1,40 +0,0 @@ -.panels-sample-panels { - min-height: 320px; - min-width: 320px; -} - -.panels-sample-panels > * { - border: 2px solid #333; - font-size: 5em; - text-align: center; -} - -.panels-sample-wide > * { - min-width: 50%; -} - -.panels-sample-collapsible > * { - min-width: 250px; -} - -.panels-sample-spiral > * { - min-width:150px; - min-height:150px; - max-height:150px; - max-width:150px; -} - -.panels-sample-grid > * { - min-width:150px; - min-height:150px; - max-height:150px; - max-width:150px; -} -.arranger-scroller { -} - -@media screen and (max-width: 480px) { - .arranger-scroller { - max-height: 270px; - } -} diff --git a/lib/layout/panels/samples/PanelsSample.html b/lib/layout/panels/samples/PanelsSample.html deleted file mode 100644 index a28c3a1..0000000 --- a/lib/layout/panels/samples/PanelsSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Panels Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSample.js b/lib/layout/panels/samples/PanelsSample.js deleted file mode 100644 index 973cb61..0000000 --- a/lib/layout/panels/samples/PanelsSample.js +++ /dev/null @@ -1,108 +0,0 @@ -enyo.kind({ - name: "enyo.sample.MyGridArranger", - kind: "GridArranger", - colHeight: "150", - colWidth: "150" -}); - -enyo.kind({ - name: "enyo.sample.PanelsSample", - kind: "FittableRows", - classes: "enyo-fit", - components: [ - {kind: "FittableColumns", noStretch: true, classes: "onyx-toolbar onyx-toolbar-inline", components: [ - {kind: "Scroller", thumb: false, fit: true, touch: true, vertical: "hidden", style: "margin: 0;", components: [ - {classes: "onyx-toolbar-inline", style: "white-space: nowrap;", components: [ - {kind: "onyx.MenuDecorator", components: [ - {content:"Arranger"}, - {name:"arrangerPicker", kind: "onyx.Menu", maxHeight: 360, floating: true, onSelect:"arrangerSelected"} - ]}, - {kind: "onyx.Button", content: "Previous", ontap: "prevPanel"}, - {kind: "onyx.Button", content: "Next", ontap: "nextPanel"}, - {kind: "onyx.InputDecorator", style: "width: 60px;", components: [ - {kind: "onyx.Input", value: 0, onchange: "gotoPanel"} - ]}, - {kind: "onyx.Button", content: "Go", ontap: "gotoPanel"}, - {kind: "onyx.Button", content: "Add", ontap: "addPanel"}, - {kind: "onyx.Button", content: "Delete", ontap: "deletePanel"} - ]} - ]} - ]}, - {kind: "Panels", name:"samplePanels", fit:true, realtimeFit: true, classes: "panels-sample-panels enyo-border-box", components: [ - {content:0, style:"background:red;"}, - {content:1, style:"background:orange;"}, - {content:2, style:"background:yellow;"}, - {content:3, style:"background:green;"}, - {content:4, style:"background:blue;"}, - {content:5, style:"background:indigo;"}, - {content:6, style:"background:violet;"} - ]} - ], - panelArrangers: [ - {name: "CardArranger", arrangerKind: "CardArranger"}, - {name: "CardSlideInArranger", arrangerKind: "CardSlideInArranger"}, - {name: "CarouselArranger", arrangerKind: "CarouselArranger", classes: "panels-sample-wide"}, - {name: "CollapsingArranger", arrangerKind: "CollapsingArranger", classes: "panels-sample-collapsible"}, - {name: "LeftRightArranger", arrangerKind: "LeftRightArranger"}, - {name: "TopBottomArranger", arrangerKind: "TopBottomArranger", classes: "panels-sample-topbottom"}, - {name: "SpiralArranger", arrangerKind: "SpiralArranger", classes: "panels-sample-spiral"}, - {name: "GridArranger", arrangerKind: "enyo.sample.MyGridArranger", classes: "panels-sample-grid"}, - {name: "DockRightArranger", arrangerKind: "DockRightArranger", classes: "panels-sample-collapsible"} - ], - bgcolors: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"], - create: function() { - this.inherited(arguments); - for (var i=0; i * { - width: 320px; - background-color: #EAEAEA; - -moz-box-shadow: -4px 0 4px rgba(0,0,0,0.3); - -webkit-box-shadow: -4px 0 4px rgba(0,0,0,0.3); - box-shadow: -4px 0 4px rgba(0,0,0,0.3); -} - -.panels-sample-sliding-item { - padding: 10px; - border-bottom: 1px solid black; -} - -.panels-sample-sliding-content { - text-align: left; - padding: 10px; -} \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSlidingSample.html b/lib/layout/panels/samples/PanelsSlidingSample.html deleted file mode 100644 index f0644c0..0000000 --- a/lib/layout/panels/samples/PanelsSlidingSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Panels Sliding App Example - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/panels/samples/PanelsSlidingSample.js b/lib/layout/panels/samples/PanelsSlidingSample.js deleted file mode 100644 index a1fb7e8..0000000 --- a/lib/layout/panels/samples/PanelsSlidingSample.js +++ /dev/null @@ -1,35 +0,0 @@ -enyo.kind({ - name: "enyo.sample.PanelsSlidingSample", - kind: "FittableRows", - classes: "onyx enyo-fit", - components: [ - {kind: "onyx.Toolbar", components: [ - {content: "Realtime"}, - {kind: "onyx.Checkbox", onchange: "checkboxChange"} - ]}, - {kind: "Panels", fit: true, classes: "panels-sample-sliding-panels", arrangerKind: "CollapsingArranger", wrap: false, components: [ - {name: "left", components: [ - {kind: "List", classes: "enyo-fit", touch: true, count: 1000, onSetupItem: "setupItem", item: "item1", components: [ - {name: "item1", classes: "panels-sample-sliding-item"} - ]} - ]}, - {name: "middle", components: [ - {kind: "List", classes: "enyo-fit", touch: true, count: 1000, onSetupItem: "setupItem", item: "item2", components: [ - {name: "item2", classes: "panels-sample-sliding-item"} - ]} - ]}, - {name: "body", fit: true, components: [ - {kind: "Scroller", classes: "enyo-fit", touch: true, components: [ - {classes: "panels-sample-sliding-content", content: "Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old. Broke, down dumb hospitality firewood chitlins. Has mud tired uncle everlastin' cold, out. Hauled thar, up thar tar heffer quarrel farmer fish water is. Simple gritts dogs soap give kickin'. Ain't shiney water range, preacher java rent thar go. Skinned wirey tin farm, trespassin' it, rodeo. Said roped caught creosote go simple. Buffalo butt, jig fried commencin' cipherin' maw, wash. Round-up barefoot jest bible rottgut sittin' trailer shed jezebel. Crop old over poker drinkin' dirt where tools skinned, city-slickers tools liniment mush tarnation. Truck lyin' snakeoil creosote, old a inbred pudneer, slap dirty cain't. Hairy, smokin', nothin' highway hootch pigs drinkin', barefoot bootleg hoosegow mule. Tax-collectors uncle wuz, maw watchin' had jumpin' got redblooded gimmie truck shootin' askin' hootch. No fat ails fire soap cabin jail, reckon if trespassin' fixin' rustle jest liniment. Ya huntin' catfish shot good bankrupt. Fishin' sherrif has, fat cooked shed old."} - ]} - ]} - ]} - ], - setupItem: function(inSender, inEvent) { - this.$[inSender.item].setContent("This is row number: " + inEvent.index); - }, - checkboxChange: function(inSender) { - this.log(); - this.$.panels.realtimeFit = inSender.getValue(); - } -}); \ No newline at end of file diff --git a/lib/layout/panels/samples/assets/search-input-search.png b/lib/layout/panels/samples/assets/search-input-search.png deleted file mode 100644 index 36bf1b5161e9d6b22273b681e43c85859c7c8914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/lib/layout/panels/samples/assets/spinner-large.gif b/lib/layout/panels/samples/assets/spinner-large.gif deleted file mode 100644 index ee786953dafde87dea34cc8449ba0ef1751e25ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 zcmciDSx{3~00!U)H>$=Sx5pEl!}QW!GH+}t+)Ud2NwuM0|7x0ssUL<2w@8* zW&vXWBWnUt0z@ciSrTLkC|X1TrBFl$I|J5srhO?*;zMUDojTKL&%=4SXYRS*|Ia;V zUx42(4<-e)6Z95j8Y?R+TrPKZc6NDrnMfoml}a2Aw|n<)tyY_yoNQk5=Y(BZd%!m& znC^4Pcl%a1%QeO)*x&8xNvD{}r=l?DW0IpWOg8gETmmy{YfSv<1Q7N&0FE%OaxuNb zv?&NMtnUv{-QD$ixML;4i60eHP7tnVWLMVqjO18cg#~_lzHPCAu??vD$VdO|&09-^ zRDN7=-UWS>YvEVZ?7G%+!aMCSxE|RZfkB^0fn3dcLPQ46Jo6Um3VjoHBofZKr(mEQ z7fUFK9p?y5fD|8+NK4DE$*#-GHQ5)N+WGWD;vDpt7E^R zS5@@%>hyj0`(@qydybt+$@n{j$C$B4nYafzqxhku;eqmL{iJ@pccEwg<;?7o*M`-A zBYy=(E0GW%bZ!{(^6QVAT(sKQ1;xpAXzK|c=Hyb|&zsoV?wM@=HfvtZT$lTPSH#Uo zN3<0{%o!Df;i=KW6gkW%q578%$t0_vQUPoNB@utlFXi%SE}k8GCd{6>_bcJ1BcTGR z5m-@qBfdy_ie;a(wb;8JP;E@l3~aJ%Y4*~f8gFgysH+mzbSliifk9G_^KjHz!zfNm z7`xa;8h5xye2#ly=o%`Yxj)@EsasSm^v%z`A$=%O-QZ?raSXu-)M<7-)m?c_onFUi zp5Z#6tje~a*<6bNj-&0@+Dkh^8jkoL{G=OXxTe!41^VwDXFQiV8}Pm1;iGFh_PBXM znUIXkTy7pOzrY#>C&OWdwuoqiT?ic(4+xNn9A|z!9Cgu)CQCrp#JSW1s0x}Qx~l0y znM^JeMM{J=#U&kGrVa;eN}UX6sg;a}_y*D#yOub9{4r63A9>L>$eYm{iTcGZGm*F| zarpff|DHIo!?|PxCF++I6p&+CEE`E1c^hoXQ=lJMgs0)Xf|qJ89=J8R^lPUwqRtLs zpGX6((Ebi`ogatVS;Mu=bvN`-q6?s_c%cV}bNlyDzx3t4*t z+gN)$UgJ=su8&vYZYZiy=0yBu@;+NI>yhYz0wQjiR*R>oFGR)wB+x0yVwuzb2E;KG z67TP~m;jm9uxv^OEfJZ<1K@>hWC?}FLW#*z9~7S_@Q4e`D=AO}*s9X)tcs( z)_3JLgIS%2zreL;Lk?WUh>4}x!EiZNN9}X(cQArt>+w(>WJ0^SNOQBrpjlAQx6I8h zt$xgWaDy2wM8;)6rJ3_Z%+pPOG$SX3Np?tqU3$B`{X^n+RYBwI zL__N=p@-%6&`LeMM79-hgQC)?WEPMtb+{rdG)RaH-(JUMsn+|#E|jg5^N z7#L>GoSBxEcIM2P|Ns9h{^#~{4GDI33~)8lGhk)}N-O?kVdVmvrUPUHDSie97N-v< zGpEh8XczsY!u2sE{E^Cy1w4|E6lN^oxcN{fu20l=q5U$Khm)QnGb{K^KWY1ZGy>f3j8qEXrAYw_(GDG+gX1D$CnAG+*uHwVgs7P2@Wd*gPmVi zx$;F;->GC^&Jj(Xw4h^M^hJ>j<;8ku@>-l0G#iDqwLVk~;LvJxWe}B_q=YbpiGc~> z7|qGvCiYJzENd^WN%_gZlVG%_bJemG9k(!(RuLV?Yk!PxH7`)G$=i9x!O(zHgvl4l zF$@fBK&OBL#^8d^=T%!zF5PhGZ%4Dom2}y2iR;7{3dkQ|xW0f#esO%0l1;1IL&e2w zr97^wTKsWA3K<5tV@y8SZtmIhqgAwM*);X87N?#|3wT~AYdC2qy9TFpPWJGfugKT3 Wq>R~sp}+a@gG7sHw - - - - Menu Test - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/panels/samples/package.js b/lib/layout/panels/samples/package.js deleted file mode 100644 index b129396..0000000 --- a/lib/layout/panels/samples/package.js +++ /dev/null @@ -1,8 +0,0 @@ -enyo.depends( - "PanelsSample.css", - "PanelsSample.js", - "PanelsFlickrSample.css", - "PanelsFlickrSample.js", - "PanelsSlidingSample.css", - "PanelsSlidingSample.js" -); \ No newline at end of file diff --git a/lib/layout/panels/source/Panels.css b/lib/layout/panels/source/Panels.css deleted file mode 100644 index 2e79349..0000000 --- a/lib/layout/panels/source/Panels.css +++ /dev/null @@ -1,12 +0,0 @@ -.enyo-panels { -} - -.enyo-panels-fit-narrow { -} - -@media all and (max-width: 800px) { - .enyo-panels-fit-narrow > * { - min-width: 100%; - max-width: 100%; - } -} \ No newline at end of file diff --git a/lib/layout/panels/source/Panels.js b/lib/layout/panels/source/Panels.js deleted file mode 100644 index 376ad4b..0000000 --- a/lib/layout/panels/source/Panels.js +++ /dev/null @@ -1,427 +0,0 @@ -/** -The _enyo.Panels_ kind is designed to satisfy a variety of common use cases for -application layout. Using _enyo.Panels_, controls may be arranged as (among -other things) a carousel, a set of collapsing panels, a card stack that fades -between panels, or a grid. - -Any Enyo control may be placed inside an _enyo.Panels_, but by convention we -refer to each of these controls as a "panel." From the set of panels in an -_enyo.Panels_, one is considered to be active. The active panel is set by index -using the _setIndex_ method. The actual layout of the panels typically changes -each time the active panel is set, such that the new active panel has the most -prominent position. - -For more information, see the -[Panels documentation](https://github.com/enyojs/enyo/wiki/Panels) in the Enyo -Developer Guide. -*/ -enyo.kind({ - name: "enyo.Panels", - classes: "enyo-panels", - published: { - /** - The index of the active panel. The layout of panels is controlled by - the layoutKind, but as a rule, the active panel is displayed in the - most prominent position. For example, in the (default) CardArranger - layout, the active panel is shown and the other panels are hidden. - */ - index: 0, - //* Controls whether the user can drag between panels. - draggable: true, - //* Controls whether the panels animate when transitioning; for example, - //* when _setIndex_ is called. - animate: true, - //* Controls whether panels "wrap around" when moving past the end. - //* The actual effect depends upon the arranger in use. - wrap: false, - //* Sets the arranger kind to be used for dynamic layout. - arrangerKind: "CardArranger", - //* By default, each panel will be sized to fit the Panels' width when - //* the screen size is narrow enough (less than 800px). Set to false - //* to avoid this behavior. - narrowFit: true - }, - events: { - /** - Fires at the start of a panel transition, when _setIndex_ is called - and also during dragging. - - _inEvent.fromIndex_ contains the index of the old panel. - - _inEvent.toIndex_ contains the index of the new panel. - */ - onTransitionStart: "", - /** - Fires at the end of a panel transition, when _setIndex_ is called - and also during dragging. - - _inEvent.fromIndex_ contains the index of the old panel. - - _inEvent.toIndex_ contains the index of the new panel. - */ - onTransitionFinish: "" - }, - //* @protected - handlers: { - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish", - onscroll: "domScroll" - }, - tools: [ - {kind: "Animator", onStep: "step", onEnd: "completed"} - ], - fraction: 0, - create: function() { - this.transitionPoints = []; - this.inherited(arguments); - this.arrangerKindChanged(); - this.narrowFitChanged(); - this.indexChanged(); - }, - rendered: function() { - this.inherited(arguments); - enyo.makeBubble(this, "scroll"); - }, - domScroll: function(inSender, inEvent) { - if (this.hasNode()) { - if (this.node.scrollLeft > 0) { - // Reset scrollLeft position - this.node.scrollLeft = 0; - } - } - }, - initComponents: function() { - this.createChrome(this.tools); - this.inherited(arguments); - }, - arrangerKindChanged: function() { - this.setLayoutKind(this.arrangerKind); - }, - narrowFitChanged: function() { - this.addRemoveClass("enyo-panels-fit-narrow", this.narrowFit); - }, - destroy: function() { - // When the entire panels is going away, take note so we don't try and do single-panel - // remove logic such as changing the index and reflowing when each panel is destroyed - this.destroying = true; - this.inherited(arguments); - }, - removeControl: function(inControl) { - this.inherited(arguments); - if (this.destroying && this.controls.length > 0 && this.isPanel(inControl)) { - this.setIndex(Math.max(this.index - 1, 0)); - this.flow(); - this.reflow(); - } - }, - isPanel: function() { - // designed to be overridden in kinds derived from Panels that have - // non-panel client controls - return true; - }, - flow: function() { - this.arrangements = []; - this.inherited(arguments); - }, - reflow: function() { - this.arrangements = []; - this.inherited(arguments); - this.refresh(); - }, - //* @public - /** - Returns an array of contained panels. - Subclasses can override this if they don't want the arranger to layout all of their children - */ - getPanels: function() { - var p = this.controlParent || this; - return p.children; - }, - //* Returns a reference to the active panel--i.e., the panel at the specified index. - getActive: function() { - var p$ = this.getPanels(); - //Constrain the index within the array of panels, needed if wrapping is enabled - var index = this.index % p$.length; - if (index < 0) { - index += p$.length; - } - return p$[index]; - }, - /** - Returns a reference to the enyo.Animator - instance used to animate panel transitions. The Panels' animator can be used - to set the duration of panel transitions, e.g.: - - this.getAnimator().setDuration(1000); - */ - getAnimator: function() { - return this.$.animator; - }, - /** - Sets the active panel to the panel specified by the given index. - Note that if the _animate_ property is set to true, the active panel - will animate into view. - */ - setIndex: function(inIndex) { - // override setIndex so that indexChanged is called - // whether this.index has actually changed or not - this.setPropertyValue("index", inIndex, "indexChanged"); - }, - /** - Sets the active panel to the panel specified by the given index. - Regardless of the value of the _animate_ property, the transition to the - next panel will not animate and will be immediate. - */ - setIndexDirect: function(inIndex) { - this.setIndex(inIndex); - this.completed(); - }, - //* Transitions to the previous panel--i.e., the panel whose index value is - //* one less than that of the current active panel. - previous: function() { - this.setIndex(this.index-1); - }, - //* Transitions to the next panel--i.e., the panel whose index value is one - //* greater than that of the current active panel. - next: function() { - this.setIndex(this.index+1); - }, - //* @protected - clamp: function(inValue) { - var l = this.getPanels().length-1; - if (this.wrap) { - // FIXME: dragging makes assumptions about direction and from->start indexes. - //return inValue < 0 ? l : (inValue > l ? 0 : inValue); - return inValue; - } else { - return Math.max(0, Math.min(inValue, l)); - } - }, - indexChanged: function(inOld) { - this.lastIndex = inOld; - this.index = this.clamp(this.index); - if (!this.dragging && this.$.animator) { - if (this.$.animator.isAnimating()) { - this.completed(); - } - this.$.animator.stop(); - if (this.hasNode()) { - if (this.animate) { - this.startTransition(); - this.$.animator.play({ - startValue: this.fraction - }); - } else { - this.refresh(); - } - } - } - }, - step: function(inSender) { - this.fraction = inSender.value; - this.stepTransition(); - }, - completed: function() { - if (this.$.animator.isAnimating()) { - this.$.animator.stop(); - } - this.fraction = 1; - this.stepTransition(); - this.finishTransition(); - }, - dragstart: function(inSender, inEvent) { - if (this.draggable && this.layout && this.layout.canDragEvent(inEvent)) { - inEvent.preventDefault(); - this.dragstartTransition(inEvent); - this.dragging = true; - this.$.animator.stop(); - return true; - } - }, - drag: function(inSender, inEvent) { - if (this.dragging) { - inEvent.preventDefault(); - this.dragTransition(inEvent); - } - }, - dragfinish: function(inSender, inEvent) { - if (this.dragging) { - this.dragging = false; - inEvent.preventTap(); - this.dragfinishTransition(inEvent); - } - }, - dragstartTransition: function(inEvent) { - if (!this.$.animator.isAnimating()) { - var f = this.fromIndex = this.index; - this.toIndex = f - (this.layout ? this.layout.calcDragDirection(inEvent) : 0); - } else { - this.verifyDragTransition(inEvent); - } - this.fromIndex = this.clamp(this.fromIndex); - this.toIndex = this.clamp(this.toIndex); - //this.log(this.fromIndex, this.toIndex); - this.fireTransitionStart(); - if (this.layout) { - this.layout.start(); - } - }, - dragTransition: function(inEvent) { - // note: for simplicity we choose to calculate the distance directly between - // the first and last transition point. - var d = this.layout ? this.layout.calcDrag(inEvent) : 0; - var t$ = this.transitionPoints, s = t$[0], f = t$[t$.length-1]; - var as = this.fetchArrangement(s); - var af = this.fetchArrangement(f); - var dx = this.layout ? this.layout.drag(d, s, as, f, af) : 0; - var dragFail = d && !dx; - if (dragFail) { - //this.log(dx, s, as, f, af); - } - this.fraction += dx; - var fr = this.fraction; - if (fr > 1 || fr < 0 || dragFail) { - if (fr > 0 || dragFail) { - this.dragfinishTransition(inEvent); - } - this.dragstartTransition(inEvent); - this.fraction = 0; - // FIXME: account for lost fraction - //this.dragTransition(inEvent); - } - this.stepTransition(); - }, - dragfinishTransition: function(inEvent) { - this.verifyDragTransition(inEvent); - this.setIndex(this.toIndex); - // note: if we're still dragging, then we're at a transition boundary - // and should fire the finish event - if (this.dragging) { - this.fireTransitionFinish(); - } - }, - verifyDragTransition: function(inEvent) { - var d = this.layout ? this.layout.calcDragDirection(inEvent) : 0; - var f = Math.min(this.fromIndex, this.toIndex); - var t = Math.max(this.fromIndex, this.toIndex); - if (d > 0) { - var s = f; - f = t; - t = s; - } - if (f != this.fromIndex) { - this.fraction = 1 - this.fraction; - } - //this.log("old", this.fromIndex, this.toIndex, "new", f, t); - this.fromIndex = f; - this.toIndex = t; - }, - refresh: function() { - if (this.$.animator && this.$.animator.isAnimating()) { - this.$.animator.stop(); - } - this.startTransition(); - this.fraction = 1; - this.stepTransition(); - this.finishTransition(); - }, - startTransition: function() { - this.fromIndex = this.fromIndex != null ? this.fromIndex : this.lastIndex || 0; - this.toIndex = this.toIndex != null ? this.toIndex : this.index; - //this.log(this.id, this.fromIndex, this.toIndex); - if (this.layout) { - this.layout.start(); - } - this.fireTransitionStart(); - }, - finishTransition: function() { - if (this.layout) { - this.layout.finish(); - } - this.transitionPoints = []; - this.fraction = 0; - this.fromIndex = this.toIndex = null; - this.fireTransitionFinish(); - }, - fireTransitionStart: function() { - var t = this.startTransitionInfo; - if (this.hasNode() && (!t || (t.fromIndex != this.fromIndex || t.toIndex != this.toIndex))) { - this.startTransitionInfo = {fromIndex: this.fromIndex, toIndex: this.toIndex}; - this.doTransitionStart(enyo.clone(this.startTransitionInfo)); - } - }, - fireTransitionFinish: function() { - var t = this.finishTransitionInfo; - if (this.hasNode() && (!t || (t.fromIndex != this.lastIndex || t.toIndex != this.index))) { - this.finishTransitionInfo = {fromIndex: this.lastIndex, toIndex: this.index}; - this.doTransitionFinish(enyo.clone(this.finishTransitionInfo)); - } - this.lastIndex=this.index; - }, - // gambit: we interpolate between arrangements as needed. - stepTransition: function() { - if (this.hasNode()) { - // select correct transition points and normalize fraction. - var t$ = this.transitionPoints; - var r = (this.fraction || 0) * (t$.length-1); - var i = Math.floor(r); - r = r - i; - var s = t$[i], f = t$[i+1]; - // get arrangements and lerp between them - var s0 = this.fetchArrangement(s); - var s1 = this.fetchArrangement(f); - this.arrangement = s0 && s1 ? enyo.Panels.lerp(s0, s1, r) : (s0 || s1); - if (this.arrangement && this.layout) { - this.layout.flowArrangement(); - } - } - }, - fetchArrangement: function(inName) { - if ((inName != null) && !this.arrangements[inName] && this.layout) { - this.layout._arrange(inName); - this.arrangements[inName] = this.readArrangement(this.getPanels()); - } - return this.arrangements[inName]; - }, - readArrangement: function(inC) { - var r = []; - for (var i=0, c$=inC, c; (c=c$[i]); i++) { - r.push(enyo.clone(c._arranger)); - } - return r; - }, - statics: { - //* @public - /** - Returns true when window width is 800px or less. This value must be - the same as the "max-width" media query used for panel sizing in - _Panels.css_. - */ - isScreenNarrow: function() { - return enyo.dom.getWindowWidth() <= 800; - }, - //* @protected - lerp: function(inA0, inA1, inFrac) { - var r = []; - for (var i=0, k$=enyo.keys(inA0), k; (k=k$[i]); i++) { - r.push(this.lerpObject(inA0[k], inA1[k], inFrac)); - } - return r; - }, - lerpObject: function(inNew, inOld, inFrac) { - var b = enyo.clone(inNew), n, o; - // inOld might be undefined when deleting panels - if (inOld) { - for (var i in inNew) { - n = inNew[i]; - o = inOld[i]; - if (n != o) { - b[i] = n - (n - o) * inFrac; - } - } - } - return b; - } - } -}); \ No newline at end of file diff --git a/lib/layout/panels/source/arrangers/Arranger.css b/lib/layout/panels/source/arrangers/Arranger.css deleted file mode 100644 index 9135a32..0000000 --- a/lib/layout/panels/source/arrangers/Arranger.css +++ /dev/null @@ -1,25 +0,0 @@ -.enyo-arranger { - position: relative; - overflow: hidden; -} - -.enyo-arranger.enyo-fit { - position: absolute; -} - -.enyo-arranger > * { - position: absolute; - left: 0; - top: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.enyo-arranger-fit > * { - /* override any width/height set on panels */ - width: 100% !important; - height: 100% !important; - min-width: 0 !important; - min-height: 0 !important; -} diff --git a/lib/layout/panels/source/arrangers/Arranger.js b/lib/layout/panels/source/arrangers/Arranger.js deleted file mode 100644 index 2fab3dd..0000000 --- a/lib/layout/panels/source/arrangers/Arranger.js +++ /dev/null @@ -1,230 +0,0 @@ -/** - _enyo.Arranger_ is an enyo.Layout that considers - one of the controls it lays out as active. The other controls are placed - relative to the active control as makes sense for the layout. - - Arranger supports dynamic layouts, meaning it's possible to transition - between its layouts via animation. Typically, arrangers should lay out - controls using CSS transforms, since these are optimized for animation. To - support this, the controls in an Arranger are absolutely positioned, and - the Arranger kind has an `accelerated` property, which marks controls for - CSS compositing. The default setting of "auto" ensures that this will occur - if enabled by the platform. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "enyo.Arranger", - kind: "Layout", - layoutClass: "enyo-arranger", - /** - Sets controls being laid out to use CSS compositing. A setting of "auto" - will mark controls for compositing if the platform supports it. - */ - accelerated: "auto", - //* Property of the drag event used to calculate the amount a drag moves the layout - dragProp: "ddx", - //* Property of the drag event used to calculate the direction of a drag - dragDirectionProp: "xDirection", - //* Property of the drag event used to calculate whether a drag should occur - canDragProp: "horizontal", - /** - If set to true, transitions between non-adjacent arrangements will go - through the intermediate arrangements. This is useful when direct - transitions between arrangements would be visually jarring. - */ - incrementalPoints: false, - /** - Called when removing an arranger (for example, when switching a Panels - control to a different arrangerKind). Subclasses should implement this - function to reset whatever properties they've changed on child controls. - You *must* call the superclass implementation in your subclass's - _destroy_ function. - */ - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - c._arranger = null; - } - this.inherited(arguments); - }, - /** - Arranges the given array of controls (_inC_) in the layout specified by - _inName_. When implementing this method, rather than apply styling - directly to controls, call _arrangeControl(inControl, inArrangement)_ - with an _inArrangement_ object with styling settings. These will then be - applied via the _flowControl(inControl, inArrangement)_ method. - */ - arrange: function(inC, inName) { - }, - /** - Sizes the controls in the layout. This method is called only at reflow - time. Note that sizing is separated from other layout done in the - _arrange_ method because it is expensive and not suitable for dynamic - layout. - */ - size: function() { - }, - /** - Called when a layout transition begins. Implement this method to perform - tasks that should only occur when a transition starts; for example, some - controls could be shown or hidden. In addition, the _transitionPoints_ - array may be set on the container to dictate the named arrangments - between which the transition occurs. - */ - start: function() { - var f = this.container.fromIndex, t = this.container.toIndex; - var p$ = this.container.transitionPoints = [f]; - // optionally add a transition point for each index between from and to. - if (this.incrementalPoints) { - var d = Math.abs(t - f) - 2; - var i = f; - while (d >= 0) { - i = i + (t < f ? -1 : 1); - p$.push(i); - d--; - } - } - p$.push(this.container.toIndex); - }, - /** - Called when a layout transition completes. Implement this method to - perform tasks that should only occur when a transition ends; for - example, some controls could be shown or hidden. - */ - finish: function() { - }, - /** - Called when dragging the layout, this method returns the difference in - pixels between the arrangement _inA0_ for layout setting _inI0_ and - arrangement _inA1_ for layout setting _inI1_. This data is used to calculate - the percentage that a drag should move the layout between two active states. - */ - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - }, - //* @protected - canDragEvent: function(inEvent) { - return inEvent[this.canDragProp]; - }, - calcDragDirection: function(inEvent) { - return inEvent[this.dragDirectionProp]; - }, - calcDrag: function(inEvent) { - return inEvent[this.dragProp]; - }, - drag: function(inDp, inAn, inA, inBn, inB) { - var f = this.measureArrangementDelta(-inDp, inAn, inA, inBn, inB); - return f; - }, - measureArrangementDelta: function(inX, inI0, inA0, inI1, inA1) { - var d = this.calcArrangementDifference(inI0, inA0, inI1, inA1); - var s = d ? inX / Math.abs(d) : 0; - s = s * (this.container.fromIndex > this.container.toIndex ? -1 : 1); - //enyo.log("delta", s); - return s; - }, - _arrange: function(inIndex) { - // guard against being called before we've been rendered - if (!this.containerBounds) { - this.reflow(); - } - var c$ = this.getOrderedControls(inIndex); - this.arrange(c$, inIndex); - }, - arrangeControl: function(inControl, inArrangement) { - inControl._arranger = enyo.mixin(inControl._arranger || {}, inArrangement); - }, - // called before HTML is generated - flow: function() { - this.c$ = [].concat(this.container.getPanels()); - this.controlsIndex = 0; - for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { - enyo.dom.accelerate(c, this.accelerated); - if (enyo.platform.safari) { - // On Safari-desktop, sometimes having the panel's direct child set to accelerate isn't sufficient - // this is most often the case with Lists contained inside another control, inside a Panels - var grands=c.children; - for (var j=0, kid; (kid=grands[j]); j++) { - enyo.dom.accelerate(kid, this.accelerated); - } - } - } - }, - // called during "rendered" phase - reflow: function() { - var cn = this.container.hasNode(); - this.containerBounds = cn ? {width: cn.clientWidth, height: cn.clientHeight} : {}; - this.size(); - }, - flowArrangement: function() { - var a = this.container.arrangement; - if (a) { - for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { - this.flowControl(c, a[i]); - } - } - }, - //* @public - /** - Lays out the control (_inControl_) according to the settings stored in - the _inArrangment_ object. By default, _flowControl_ will apply settings - of left, top, and opacity. This method should only be implemented to - apply other settings made via _arrangeControl_. - */ - flowControl: function(inControl, inArrangement) { - enyo.Arranger.positionControl(inControl, inArrangement); - var o = inArrangement.opacity; - if (o != null) { - enyo.Arranger.opacifyControl(inControl, o); - } - }, - //* @protected - // Gets an array of controls arranged in state order. - // note: optimization, dial around a single array. - getOrderedControls: function(inIndex) { - var whole = Math.floor(inIndex); - var a = whole - this.controlsIndex; - var sign = a > 0; - var c$ = this.c$ || []; - for (var i=0; i 0.99 ? 1 : (o < 0.01 ? 0 : o); - // note: we only care about ie8 - if (enyo.platform.ie < 9) { - inControl.applyStyle("filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (o * 100) + ")"); - } else { - inControl.applyStyle("opacity", o); - } - } - } -}); diff --git a/lib/layout/panels/source/arrangers/CardArranger.js b/lib/layout/panels/source/arrangers/CardArranger.js deleted file mode 100644 index 81e882a..0000000 --- a/lib/layout/panels/source/arrangers/CardArranger.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - _enyo.CardArranger_ is an enyo.Arranger that - displays only one active control. The non-active controls are hidden with - _setShowing(false)_. Transitions between arrangements are handled by fading - from one control to the next. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.CardArranger", - kind: "Arranger", - //* @protected - layoutClass: "enyo-arranger enyo-arranger-fit", - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - return this.containerBounds.width; - }, - arrange: function(inC, inName) { - for (var i=0, c, b, v; (c=inC[i]); i++) { - v = (i === 0) ? 1 : 0; - this.arrangeControl(c, {opacity: v}); - } - }, - start: function() { - this.inherited(arguments); - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - var wasShowing=c.showing; - c.setShowing(i == this.container.fromIndex || i == (this.container.toIndex)); - if (c.showing && !wasShowing) { - c.resized(); - } - } - }, - finish: function() { - this.inherited(arguments); - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - c.setShowing(i == this.container.toIndex); - } - }, - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - enyo.Arranger.opacifyControl(c, 1); - if (!c.showing) { - c.setShowing(true); - } - } - this.inherited(arguments); - } -}); diff --git a/lib/layout/panels/source/arrangers/CardSlideInArranger.js b/lib/layout/panels/source/arrangers/CardSlideInArranger.js deleted file mode 100644 index 83c45d0..0000000 --- a/lib/layout/panels/source/arrangers/CardSlideInArranger.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - _enyo.CardSlideInArranger_ is an enyo.Arranger - that displays only one active control. The non-active controls are hidden - with _setShowing(false)_. Transitions between arrangements are handled by - sliding the new control over the current one. - - Note that CardSlideInArranger always slides controls in from the right. If - you want an arranger that slides to the right and left, try - enyo.LeftRightArranger. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.CardSlideInArranger", - kind: "CardArranger", - //* @protected - start: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - var wasShowing=c.showing; - c.setShowing(i == this.container.fromIndex || i == (this.container.toIndex)); - if (c.showing && !wasShowing) { - c.resized(); - } - } - var l = this.container.fromIndex; - i = this.container.toIndex; - this.container.transitionPoints = [ - i + "." + l + ".s", - i + "." + l + ".f" - ]; - }, - finish: function() { - this.inherited(arguments); - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - c.setShowing(i == this.container.toIndex); - } - }, - arrange: function(inC, inName) { - var p = inName.split("."); - var f = p[0], s= p[1], starting = (p[2] == "s"); - var b = this.containerBounds.width; - for (var i=0, c$=this.container.getPanels(), c, v; (c=c$[i]); i++) { - v = b; - if (s == i) { - v = starting ? 0 : -b; - } - if (f == i) { - v = starting ? b : 0; - } - if (s == i && s == f) { - v = 0; - } - this.arrangeControl(c, {left: v}); - } - }, - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - enyo.Arranger.positionControl(c, {left: null}); - } - this.inherited(arguments); - } -}); diff --git a/lib/layout/panels/source/arrangers/CarouselArranger.js b/lib/layout/panels/source/arrangers/CarouselArranger.js deleted file mode 100644 index 253000b..0000000 --- a/lib/layout/panels/source/arrangers/CarouselArranger.js +++ /dev/null @@ -1,117 +0,0 @@ -/** - _enyo.CarouselArranger_ is an enyo.Arranger - that displays the active control, along with some number of inactive - controls to fill the available space. The active control is positioned on - the left side of the container, and the rest of the views are laid out to - the right. - - One of the controls may have _fit: true_ set, in which case it will take up - any remaining space after all of the other controls have been sized. - - For best results with CarouselArranger, you should set a minimum width for - each control via a CSS style, e.g., _min-width: 25%_ or _min-width: 250px_. - - Transitions between arrangements are handled by sliding the new controls in - from the right and sliding the old controls off to the left. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.CarouselArranger", - kind: "Arranger", - //* @protected - size: function() { - var c$ = this.container.getPanels(); - var padding = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}; - var pb = this.containerBounds; - var i, e, s, m, c; - pb.height -= padding.top + padding.bottom; - pb.width -= padding.left + padding.right; - // used space - var fit; - for (i=0, s=0; (c=c$[i]); i++) { - m = enyo.dom.calcMarginExtents(c.hasNode()); - c.width = c.getBounds().width; - c.marginWidth = m.right + m.left; - s += (c.fit ? 0 : c.width) + c.marginWidth; - if (c.fit) { - fit = c; - } - } - if (fit) { - var w = pb.width - s; - fit.width = w >= 0 ? w : fit.width; - } - for (i=0, e=padding.left; (c=c$[i]); i++) { - c.setBounds({top: padding.top, bottom: padding.bottom, width: c.fit ? c.width : null}); - } - }, - arrange: function(inC, inName) { - if (this.container.wrap) { - this.arrangeWrap(inC, inName); - } else { - this.arrangeNoWrap(inC, inName); - } - }, - arrangeNoWrap: function(inC, inName) { - var i, aw, cw, c; - var c$ = this.container.getPanels(); - var s = this.container.clamp(inName); - var nw = this.containerBounds.width; - // do we have enough content to fill the width? - for (i=s, cw=0; (c=c$[i]); i++) { - cw += c.width + c.marginWidth; - if (cw > nw) { - break; - } - } - // if content width is less than needed, adjust starting point index and offset - var n = nw - cw; - var o = 0; - if (n > 0) { - var s1 = s; - for (i=s-1, aw=0; (c=c$[i]); i--) { - aw += c.width + c.marginWidth; - if (n - aw <= 0) { - o = (n - aw); - s = i; - break; - } - } - } - // arrange starting from needed index with detected offset so we fill space - var w, e; - for (i=0, e=this.containerPadding.left + o; (c=c$[i]); i++) { - w = c.width + c.marginWidth; - if (i < s) { - this.arrangeControl(c, {left: -w}); - } else { - this.arrangeControl(c, {left: Math.floor(e)}); - e += w; - } - } - }, - arrangeWrap: function(inC, inName) { - for (var i=0, e=this.containerPadding.left, m, c; (c=inC[i]); i++) { - this.arrangeControl(c, {left: e}); - e += c.width + c.marginWidth; - } - }, - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - var i = Math.abs(inI0 % this.c$.length); - return inA0[i].left - inA1[i].left; - }, - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - enyo.Arranger.positionControl(c, {left: null, top: null}); - c.applyStyle("top", null); - c.applyStyle("bottom", null); - c.applyStyle("left", null); - c.applyStyle("width", null); - } - this.inherited(arguments); - } -}); diff --git a/lib/layout/panels/source/arrangers/CollapsingArranger.js b/lib/layout/panels/source/arrangers/CollapsingArranger.js deleted file mode 100644 index 1ca6cd3..0000000 --- a/lib/layout/panels/source/arrangers/CollapsingArranger.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - _enyo.CollapsingArranger_ is an enyo.Arranger - that displays the active control, along with some number of inactive - controls to fill the available space. The active control is positioned on - the left side of the container and the rest of the views are laid out to the - right. The last control, if visible, will expand to fill whatever space is - not taken up by the previous controls. - - For best results with CollapsingArranger, you should set a minimum width - for each control via a CSS style, e.g., _min-width: 25%_ or - _min-width: 250px_. - - Transitions between arrangements are handled by sliding the new control in - from the right and collapsing the old control to the left. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.CollapsingArranger", - kind: "CarouselArranger", - /** - The "peekWidth" property specifies the amount each panel should be - offset from the left when it is selected. This allows controls on the - underlying panel to the left of the selected one to be partially - revealed. - */ - peekWidth: 0, - //* @protected - size: function() { - this.clearLastSize(); - this.inherited(arguments); - }, - // clear size from last if it's not actually the last - // (required for adding another control) - clearLastSize: function() { - for (var i=0, c$=this.container.getPanels(), c; (c=c$[i]); i++) { - if (c._fit && i != c$.length-1) { - c.applyStyle("width", null); - c._fit = null; - } - } - }, - constructor: function() { - this.inherited(arguments); - this.peekWidth = this.container.peekWidth != null ? this.container.peekWidth : this.peekWidth; - }, - arrange: function(inC, inIndex) { - var c$ = this.container.getPanels(); - for (var i=0, e=this.containerPadding.left, m, c, n=0; (c=c$[i]); i++) { - if(c.getShowing()){ - this.arrangeControl(c, {left: e + n * this.peekWidth}); - if (i >= inIndex) { - e += c.width + c.marginWidth - this.peekWidth; - } - n++; - } else { - this.arrangeControl(c, {left: e}); - if (i >= inIndex) { - e += c.width + c.marginWidth; - } - } - // FIXME: overdragging-ish - if (i == c$.length - 1 && inIndex < 0) { - this.arrangeControl(c, {left: e - inIndex}); - } - } - }, - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - var i = this.container.getPanels().length-1; - return Math.abs(inA1[i].left - inA0[i].left); - }, - flowControl: function(inControl, inA) { - this.inherited(arguments); - if (this.container.realtimeFit) { - var c$ = this.container.getPanels(); - var l = c$.length-1; - var last = c$[l]; - if (inControl == last) { - this.fitControl(inControl, inA.left); - } - } - - }, - finish: function() { - this.inherited(arguments); - if (!this.container.realtimeFit && this.containerBounds) { - var c$ = this.container.getPanels(); - var a$ = this.container.arrangement; - var l = c$.length-1; - var c = c$[l]; - this.fitControl(c, a$[l].left); - } - }, - fitControl: function(inControl, inOffset) { - inControl._fit = true; - inControl.applyStyle("width", (this.containerBounds.width - inOffset) + "px"); - inControl.resized(); - } -}); diff --git a/lib/layout/panels/source/arrangers/DockRightArranger.js b/lib/layout/panels/source/arrangers/DockRightArranger.js deleted file mode 100644 index 47eab1a..0000000 --- a/lib/layout/panels/source/arrangers/DockRightArranger.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - _enyo.DockRightArranger_ is an enyo.Arranger - that displays the active control, along with some number of inactive - controls to fill the available space. The active control is positioned on - the right side of the container and the rest of the views are laid out to the - right. - - For best results with DockRightArranger, you should set a minimum width - for each control via a CSS style, e.g., _min-width: 25%_ or - _min-width: 250px_. - - Transitions between arrangements are handled by sliding the new control in - from the right. If the width of the old control(s) can fit within the container, - they will slide to the left. If not, the old control(s) will collapse to the left. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.DockRightArranger", - kind: "Arranger", - //* If true, the base panel (index 0) will fill the width of the container, - //* while newer controls will slide in and collapse on top of it - basePanel: false, - //* How many px should panels overlap - overlap: 0, - //* Column width - layoutWidth: 0, - //* @protected - constructor: function() { - this.inherited(arguments); - this.overlap = this.container.overlap != null ? this.container.overlap : this.overlap; - this.layoutWidth = this.container.layoutWidth != null ? this.container.layoutWidth : this.layoutWidth; - }, - size: function() { - var c$ = this.container.getPanels(); - var padding = this.containerPadding = this.container.hasNode() ? enyo.dom.calcPaddingExtents(this.container.node) : {}; - var pb = this.containerBounds; - var i, m, c; - pb.width -= padding.left + padding.right; - var nw = pb.width; - var len = c$.length; - // panel arrangement positions - this.container.transitionPositions = {}; - - for (i=0; (c=c$[i]); i++) { - c.width = ((i===0) && (this.container.basePanel)) ? nw : c.getBounds().width; - } - - for (i=0; (c=c$[i]); i++) { - - if ((i===0) && (this.container.basePanel)) { - c.setBounds({width: nw}); - } - c.setBounds({top: padding.top, bottom: padding.bottom}); - - for (j=0; (c=c$[j]); j++) { - var xPos; - // index 0 always should always be left-aligned at 0px - if ((i===0) && (this.container.basePanel)) { - xPos = 0; - // else newer panels should be positioned off the viewport - } else if (j < i) { - xPos = nw; - // else active panel should be right-aligned - } else if (i === j) { - var offset = nw > this.layoutWidth ? this.overlap : 0; - xPos = (nw - c$[i].width) + offset; - } else { - break; - } - this.container.transitionPositions[i + "." + j] = xPos; - } - - if (j < len) { - var leftAlign = false; - for (k=i+1; k nw ) { - //} else if ( (c$[i].width + c$[k].width) > nw ) { - offset = 0; - leftAlign = true; - } else { - offset = c$[i].width - this.overlap; - for (m=i; menyo.Arranger - that displays the active control and some of the previous and next controls. - The active control is centered horizontally in the container, and the - previous and next controls are laid out to the left and right, respectively. - - Transitions between arrangements are handled by sliding the new control - in from the right and sliding the active control out to the left. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.LeftRightArranger", - kind: "Arranger", - //* The margin width (i.e., how much of the previous and next controls - //* are visible) in pixels - margin: 40, - //* @protected - axisSize: "width", - offAxisSize: "height", - axisPosition: "left", - constructor: function() { - this.inherited(arguments); - this.margin = this.container.margin != null ? this.container.margin : this.margin; - }, - size: function() { - var c$ = this.container.getPanels(); - var port = this.containerBounds[this.axisSize]; - var box = port - this.margin -this.margin; - for (var i=0, b, c; (c=c$[i]); i++) { - b = {}; - b[this.axisSize] = box; - b[this.offAxisSize] = "100%"; - c.setBounds(b); - } - }, - start: function() { - this.inherited(arguments); - - var s = this.container.fromIndex; - var f = this.container.toIndex; - var c$ = this.getOrderedControls(f); - var o = Math.floor(c$.length/2); - - for (var i=0, c; (c=c$[i]); i++) { - if (s > f){ - if (i == (c$.length - o)){ - c.applyStyle("z-index", 0); - } else { - c.applyStyle("z-index", 1); - } - } else { - if (i == (c$.length-1 - o)){ - c.applyStyle("z-index", 0); - } else { - c.applyStyle("z-index", 1); - } - } - } - }, - arrange: function(inC, inIndex) { - var i,c,v,b; - if (this.container.getPanels().length==1){ - b = {}; - b[this.axisPosition] = this.margin; - this.arrangeControl(this.container.getPanels()[0], b); - return; - } - var o = Math.floor(this.container.getPanels().length/2); - var c$ = this.getOrderedControls(Math.floor(inIndex)-o); - var box = this.containerBounds[this.axisSize] - this.margin -this.margin; - var e = this.margin - box * o; - for (i=0; (c=c$[i]); i++) { - b = {}; - b[this.axisPosition] = e; - this.arrangeControl(c, b); - e += box; - } - }, - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - if (this.container.getPanels().length==1){ - return 0; - } - - var i = Math.abs(inI0 % this.c$.length); - //enyo.log(inI0, inI1); - return inA0[i][this.axisPosition] - inA1[i][this.axisPosition]; - }, - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - enyo.Arranger.positionControl(c, {left: null, top: null}); - enyo.Arranger.opacifyControl(c, 1); - c.applyStyle("left", null); - c.applyStyle("top", null); - c.applyStyle("height", null); - c.applyStyle("width", null); - } - this.inherited(arguments); - } -}); - -//* @public -/** - _enyo.TopBottomArranger_ is an enyo.Arranger - that displays the active control and some of the previous and next controls. - The active control is centered vertically in the container, and the previous - and next controls are laid out above and below, respectively. - - Transitions between arrangements are handled by sliding the new control - in from the bottom and sliding the active control out the top. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.TopBottomArranger", - kind: "LeftRightArranger", - //* Property of the drag event used to calculate the amount a drag moves - //* the layout - dragProp: "ddy", - //* Property of the drag event used to calculate the direction of a drag - dragDirectionProp: "yDirection", - //* Property of the drag event used to calculate whether a drag should occur - canDragProp: "vertical", - //* @protected - axisSize: "height", - offAxisSize: "width", - axisPosition: "top" -}); - -//* @public -/** - _enyo.SpiralArranger_ is an enyo.Arranger that - arranges controls in a spiral. The active control is positioned on top and - the other controls are laid out in a spiral pattern below. - - Transitions between arrangements are handled by rotating the new control - up from below and rotating the active control down to the end of the spiral. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.SpiralArranger", - kind: "Arranger", - //* Always go through incremental arrangements when transitioning - incrementalPoints: true, - //* The amount of space between successive controls - inc: 20, - //* @protected - size: function() { - var c$ = this.container.getPanels(); - var b = this.containerBounds; - var w = this.controlWidth = b.width/3; - var h = this.controlHeight = b.height/3; - for (var i=0, c; (c=c$[i]); i++) { - c.setBounds({width: w, height: h}); - } - }, - arrange: function(inC, inName) { - var s = this.inc; - for (var i=0, l=inC.length, c; (c=inC[i]); i++) { - var x = Math.cos(i/l * 2*Math.PI) * i * s + this.controlWidth; - var y = Math.sin(i/l * 2*Math.PI) * i * s + this.controlHeight; - this.arrangeControl(c, {left: x, top: y}); - } - }, - start: function() { - this.inherited(arguments); - var c$ = this.getOrderedControls(this.container.toIndex); - for (var i=0, c; (c=c$[i]); i++) { - c.applyStyle("z-index", c$.length - i); - } - }, - calcArrangementDifference: function(inI0, inA0, inI1, inA1) { - return this.controlWidth; - }, - destroy: function() { - var c$ = this.container.getPanels(); - for (var i=0, c; (c=c$[i]); i++) { - c.applyStyle("z-index", null); - enyo.Arranger.positionControl(c, {left: null, top: null}); - c.applyStyle("left", null); - c.applyStyle("top", null); - c.applyStyle("height", null); - c.applyStyle("width", null); - } - this.inherited(arguments); - } -}); - -//* @public -/** - _enyo.GridArranger_ is an enyo.Arranger that - arranges controls in a grid. The active control is positioned at the - top-left of the grid and the other controls are laid out from left to right - and then from top to bottom. - - Transitions between arrangements are handled by moving the active control to - the end of the grid and shifting the other controls to the left, or up to - the previous row, to fill the space. - - For more information, see the documentation on - [Arrangers](https://github.com/enyojs/enyo/wiki/Arrangers) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "enyo.GridArranger", - kind: "Arranger", - //* Always go through incremental arrangements when transitioning - incrementalPoints: true, - //* @public - //* Column width - colWidth: 100, - //* Column height - colHeight: 100, - //* @protected - size: function() { - var c$ = this.container.getPanels(); - var w=this.colWidth, h=this.colHeight; - for (var i=0, c; (c=c$[i]); i++) { - c.setBounds({width: w, height: h}); - } - }, - arrange: function(inC, inIndex) { - var w=this.colWidth, h=this.colHeight; - var cols = Math.max(1, Math.floor(this.containerBounds.width / w)); - var c; - for (var y=0, i=0; i - - - - Slideable Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/slideable/samples/SlideableSample.js b/lib/layout/slideable/samples/SlideableSample.js deleted file mode 100644 index a125795..0000000 --- a/lib/layout/slideable/samples/SlideableSample.js +++ /dev/null @@ -1,98 +0,0 @@ -enyo.kind({ - name: "enyo.sample.SlideableSample", - classes: "enyo-unselectable enyo-fit", - style: "overflow: hidden; background-color: #000;", - components: [ - {name: "top", kind: "Slideable", axis: "v", unit: "%", min: -90, max: 0, classes: "enyo-fit slideable-sample top", onChange: "updateInfo"}, - {name: "right", kind: "Slideable", axis: "h", unit: "%", min: 0, max: 90, classes: "enyo-fit slideable-sample right", onChange: "updateInfo"}, - {name: "bottom", kind: "Slideable", axis: "v", unit: "%", min: 0, max: 90, classes: "enyo-fit slideable-sample bottom", onChange: "updateInfo"}, - {name: "left", kind: "Slideable", axis: "h", unit: "%", min: -90, max: 0, classes: "enyo-fit slideable-sample left", onChange: "updateInfo"} - ], - handlers: { - ondragstart: "suppressPanelDrag" - }, - create: function() { - this.inherited(arguments); - var slideables = []; - - for (var c in this.$) { - if (this.$[c].kind === "Slideable") { - slideables.push(this.$[c]); - } - } - this.populate(slideables); - }, - populate: function(inSlideables) { - var slideable; - for (var s in inSlideables) { - slideable = inSlideables[s]; - slideable.createComponents([ - {style: slideable.axis === "h" ? "height: 38%;" : ""}, // cheating here for the horizontal Slideables to make everything nice and (almost) centered vertically - { - kind: "enyo.sample.SlideableInfo", - layoutKind: (slideable.axis === "v") ? enyo.FittableColumnsLayout : enyo.FittableRowsLayout, - classes: "enyo-center", // cheating here for the vertical Slideables to make everything nice and centered horizontally (no effect on horizontal Slideables) - info: { - name: slideable.name, - axis: slideable.axis, - unit: slideable.unit, - min: slideable.min, - max: slideable.max, - value: slideable.value - } - } - ]); - } - }, - updateInfo: function(inSender) { - inSender.waterfallDown("onUpdateInfo", { - name: inSender.name, - axis: inSender.axis, - unit: inSender.unit, - min: inSender.min, - max: inSender.max, - value: Math.round(inSender.value) - }); - return true; - }, - // keeps the view panel from moving in Sampler app while dragging the Slideable - suppressPanelDrag: function() { - return true; - } -}); - -enyo.kind({ - name: "enyo.sample.SlideableInfo", - kind: enyo.Control, - published: { - info: null - }, - components: [ - {kind: enyo.FittableRows, classes: "slideableinfo-sample", components: [ - {name: "name"}, - {name: "axis"}, - {name: "unit"}, - {name: "min"}, - {name: "max"}, - {name: "value"} - ]} - ], - handlers: { - onUpdateInfo: "updateInfo" - }, - create: function() { - this.inherited(arguments); - this.infoChanged(); - }, - infoChanged: function() { - for (var p in this.info) { - if (this.$[p]) { - this.$[p].setContent(enyo.cap(p) + ": " + this.info[p]); - } - } - }, - updateInfo: function(inSender, inEvent) { - this.setInfo(inEvent); - return true; - } -}); \ No newline at end of file diff --git a/lib/layout/slideable/samples/package.js b/lib/layout/slideable/samples/package.js deleted file mode 100644 index 1cbe4f8..0000000 --- a/lib/layout/slideable/samples/package.js +++ /dev/null @@ -1,4 +0,0 @@ -enyo.depends( - "SlideableSample.css", - "SlideableSample.js" -); \ No newline at end of file diff --git a/lib/layout/slideable/source/Slideable.js b/lib/layout/slideable/source/Slideable.js deleted file mode 100644 index c5b3dc2..0000000 --- a/lib/layout/slideable/source/Slideable.js +++ /dev/null @@ -1,316 +0,0 @@ -/** - _enyo.Slideable_ is a control that can be dragged either horizontally or - vertically between a minimum and a maximum value. When released from - dragging, a Slideable will animate to its minimum or maximum position, - depending on the direction of the drag. - - The _min_ value specifies a position to the left of, or above, the initial - position, to which the Slideable may be dragged. - The _max_ value specifies a position to the right of, or below, the initial - position, to which the Slideable may be dragged. - The _value_ property specifies the current position of the Slideable, - between the minimum and maximum positions. - - _min_, _max_, and _value_ may be specified in units of "px" or "%". - - The _axis_ property determines whether the Slideable slides left-to-right - ("h") or up-and-down ("v"). - - The following control is placed 90% off the screen to the right, and slides - to its natural position. - - {kind: "enyo.Slideable", value: -90, min: -90, unit: "%", - classes: "enyo-fit", style: "width: 300px;", - components: [ - {content: "stuff"} - ] - } -*/ -enyo.kind({ - name: "enyo.Slideable", - kind: "Control", - published: { - //* Direction of sliding; can be "h" or "v" - axis: "h", - //* Current position of the Slideable (a value between _min_ and _max_) - value: 0, - //* Unit for _min_, _max_, and _value_; can be "px" or "%" - unit: "px", - //* A minimum value to slide to - min: 0, - //* A maximum value to slide to - max: 0, - //* When truthy, apply CSS styles to allow GPU compositing of slideable content - //* if the platform allows. - accelerated: "auto", - //* Set to false to prevent the Slideable from dragging with elasticity - //* past its _min_ or _max_ value - overMoving: true, - //* Set to false to disable dragging - draggable: true - }, - events: { - //* Fires when the Slideable finishes animating. - onAnimateFinish: "", - //* Fires when the position (i.e., _value_) of the Slideable changes. - onChange: "" - }, - //* Set to true to prevent a drag from bubbling beyond the Slideable - preventDragPropagation: false, - //* @protected - tools: [ - {kind: "Animator", onStep: "animatorStep", onEnd: "animatorComplete"} - ], - handlers: { - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish" - }, - kDragScalar: 1, - dragEventProp: "dx", - unitModifier: false, - canTransform: false, - //* @protected - create: function() { - this.inherited(arguments); - this.acceleratedChanged(); - this.transformChanged(); - this.axisChanged(); - this.valueChanged(); - this.addClass("enyo-slideable"); - }, - initComponents: function() { - this.createComponents(this.tools); - this.inherited(arguments); - }, - rendered: function() { - this.inherited(arguments); - this.canModifyUnit(); - this.updateDragScalar(); - }, - resizeHandler: function() { - this.inherited(arguments); - this.updateDragScalar(); - }, - canModifyUnit: function() { - if (!this.canTransform) { - var b = this.getInitialStyleValue(this.hasNode(), this.boundary); - // If inline style of "px" exists, while unit is "%" - if (b.match(/px/i) && (this.unit === "%")) { - // Set unitModifier - used to over-ride "%" - this.unitModifier = this.getBounds()[this.dimension]; - } - } - }, - getInitialStyleValue: function(inNode, inBoundary) { - var s = enyo.dom.getComputedStyle(inNode); - if (s) { - return s.getPropertyValue(inBoundary); - } else if (inNode && inNode.currentStyle) { - return inNode.currentStyle[inBoundary]; - } - return "0"; - }, - updateBounds: function(inValue, inDimensions) { - var inBounds = {}; - inBounds[this.boundary] = inValue; - this.setBounds(inBounds, this.unit); - - this.setInlineStyles(inValue, inDimensions); - }, - updateDragScalar: function() { - if (this.unit == "%") { - var d = this.getBounds()[this.dimension]; - this.kDragScalar = d ? 100 / d : 1; - - if (!this.canTransform) { - this.updateBounds(this.value, 100); - } - } - }, - transformChanged: function() { - this.canTransform = enyo.dom.canTransform(); - }, - acceleratedChanged: function() { - if (!(enyo.platform.android > 2)) { - enyo.dom.accelerate(this, this.accelerated); - } - }, - axisChanged: function() { - var h = this.axis == "h"; - this.dragMoveProp = h ? "dx" : "dy"; - this.shouldDragProp = h ? "horizontal" : "vertical"; - this.transform = h ? "translateX" : "translateY"; - this.dimension = h ? "width" : "height"; - this.boundary = h ? "left" : "top"; - }, - setInlineStyles: function(inValue, inDimensions) { - var inBounds = {}; - - if (this.unitModifier) { - inBounds[this.boundary] = this.percentToPixels(inValue, this.unitModifier); - inBounds[this.dimension] = this.unitModifier; - this.setBounds(inBounds); - } else { - if (inDimensions) { - inBounds[this.dimension] = inDimensions; - } else { - inBounds[this.boundary] = inValue; - } - this.setBounds(inBounds, this.unit); - } - }, - valueChanged: function(inLast) { - var v = this.value; - if (this.isOob(v) && !this.isAnimating()) { - this.value = this.overMoving ? this.dampValue(v) : this.clampValue(v); - } - // FIXME: android cannot handle nested compositing well so apply acceleration only if needed - // desktop chrome doesn't like this code path so avoid... - if (enyo.platform.android > 2) { - if (this.value) { - if (inLast === 0 || inLast === undefined) { - enyo.dom.accelerate(this, this.accelerated); - } - } else { - enyo.dom.accelerate(this, false); - } - } - - // If platform supports transforms - if (this.canTransform) { - enyo.dom.transformValue(this, this.transform, this.value + this.unit); - // else update inline styles - } else { - this.setInlineStyles(this.value, false); - } - this.doChange(); - }, - getAnimator: function() { - return this.$.animator; - }, - isAtMin: function() { - return this.value <= this.calcMin(); - }, - isAtMax: function() { - return this.value >= this.calcMax(); - }, - calcMin: function() { - return this.min; - }, - calcMax: function() { - return this.max; - }, - clampValue: function(inValue) { - var min = this.calcMin(); - var max = this.calcMax(); - return Math.max(min, Math.min(inValue, max)); - }, - dampValue: function(inValue) { - return this.dampBound(this.dampBound(inValue, this.min, 1), this.max, -1); - }, - dampBound: function(inValue, inBoundary, inSign) { - var v = inValue; - if (v * inSign < inBoundary * inSign) { - v = inBoundary + (v - inBoundary) / 4; - } - return v; - }, - percentToPixels: function(value, dimension) { - return Math.floor((dimension / 100) * value); - }, - pixelsToPercent: function(value) { - var boundary = this.unitModifier ? this.getBounds()[this.dimension] : this.container.getBounds()[this.dimension]; - return (value / boundary) * 100; - }, - // dragging - shouldDrag: function(inEvent) { - return this.draggable && inEvent[this.shouldDragProp]; - }, - isOob: function(inValue) { - return inValue > this.calcMax() || inValue < this.calcMin(); - }, - dragstart: function(inSender, inEvent) { - if (this.shouldDrag(inEvent)) { - inEvent.preventDefault(); - this.$.animator.stop(); - inEvent.dragInfo = {}; - this.dragging = true; - this.drag0 = this.value; - this.dragd0 = 0; - return this.preventDragPropagation; - } - }, - drag: function(inSender, inEvent) { - if (this.dragging) { - inEvent.preventDefault(); - var d = this.canTransform ? inEvent[this.dragMoveProp] * this.kDragScalar : this.pixelsToPercent(inEvent[this.dragMoveProp]); - var v = this.drag0 + d; - var dd = d - this.dragd0; - this.dragd0 = d; - if (dd) { - inEvent.dragInfo.minimizing = dd < 0; - } - this.setValue(v); - return this.preventDragPropagation; - } - }, - dragfinish: function(inSender, inEvent) { - if (this.dragging) { - this.dragging = false; - this.completeDrag(inEvent); - inEvent.preventTap(); - return this.preventDragPropagation; - } - }, - completeDrag: function(inEvent) { - if (this.value !== this.calcMax() && this.value != this.calcMin()) { - this.animateToMinMax(inEvent.dragInfo.minimizing); - } - }, - // animation - isAnimating: function() { - return this.$.animator.isAnimating(); - }, - play: function(inStart, inEnd) { - this.$.animator.play({ - startValue: inStart, - endValue: inEnd, - node: this.hasNode() - }); - }, - //* @public - //* Animates to the given value. - animateTo: function(inValue) { - this.play(this.value, inValue); - }, - //* Animates to the minimum value. - animateToMin: function() { - this.animateTo(this.calcMin()); - }, - //* Animates to the maximum value. - animateToMax: function() { - this.animateTo(this.calcMax()); - }, - //* @protected - animateToMinMax: function(inMin) { - if (inMin) { - this.animateToMin(); - } else { - this.animateToMax(); - } - }, - animatorStep: function(inSender) { - this.setValue(inSender.value); - return true; - }, - animatorComplete: function(inSender) { - this.doAnimateFinish(inSender); - return true; - }, - //* @public - //* Toggles between _min_ and _max_ values with animation. - toggleMinMax: function() { - this.animateToMinMax(!this.isAtMin()); - } -}); diff --git a/lib/layout/slideable/source/package.js b/lib/layout/slideable/source/package.js deleted file mode 100644 index 8c4ec43..0000000 --- a/lib/layout/slideable/source/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "Slideable.js" -); diff --git a/lib/layout/tree/package.js b/lib/layout/tree/package.js deleted file mode 100644 index 1ec0cd0..0000000 --- a/lib/layout/tree/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "source" -); \ No newline at end of file diff --git a/lib/layout/tree/samples/TreeSample.css b/lib/layout/tree/samples/TreeSample.css deleted file mode 100644 index e69de29..0000000 diff --git a/lib/layout/tree/samples/TreeSample.html b/lib/layout/tree/samples/TreeSample.html deleted file mode 100644 index e9af7ab..0000000 --- a/lib/layout/tree/samples/TreeSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Tree Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/tree/samples/TreeSample.js b/lib/layout/tree/samples/TreeSample.js deleted file mode 100644 index eb203cc..0000000 --- a/lib/layout/tree/samples/TreeSample.js +++ /dev/null @@ -1,43 +0,0 @@ -enyo.kind({ - name: "enyo.sample.TreeSample", - classes: "enyo-unselectable enyo-fit", - kind: "FittableRows", - fit: true, - components: [ - {kind: "Selection", onSelect: "select", onDeselect: "deselect"}, - {kind: "Scroller", fit: true, components: [ - {kind: "Node", icon: "assets/folder-open.png", content: "Tree", expandable: true, expanded: true, onExpand: "nodeExpand", onNodeTap: "nodeTap", components: [ - {icon: "assets/file.png", content: "Alpha"}, - {icon: "assets/folder-open.png", content: "Bravo", expandable: true, expanded: true, components: [ - {icon: "assets/file.png", content: "Bravo-Alpha"}, - {icon: "assets/file.png", content: "Bravo-Bravo"}, - {icon: "assets/file.png", content: "Bravo-Charlie"} - ]}, - {icon: "assets/folder.png", content: "Charlie", expandable: true, components: [ - {icon: "assets/file.png", content: "Charlie-Alpha"}, - {icon: "assets/file.png", content: "Charlie-Bravo"}, - {icon: "assets/file.png", content: "Charlie-Charlie"} - ]}, - {icon: "assets/folder-open.png", content: "Delta", expandable: true, expanded: true, components: [ - {icon: "assets/file.png", content: "Delta-Alpha"}, - {icon: "assets/file.png", content: "Delta-Bravo"}, - {icon: "assets/file.png", content: "Delta-Charlie"} - ]}, - {icon: "assets/file.png", content: "Epsilon"} - ]} - ]} - ], - nodeExpand: function(inSender, inEvent) { - inSender.setIcon("assets/" + (inSender.expanded ? "folder-open.png" : "folder.png")); - }, - nodeTap: function(inSender, inEvent) { - var node = inEvent.originator; - this.$.selection.select(node.id, node); - }, - select: function(inSender, inEvent) { - inEvent.data.$.caption.applyStyle("background-color", "lightblue"); - }, - deselect: function(inSender, inEvent) { - inEvent.data.$.caption.applyStyle("background-color", null); - } -}); \ No newline at end of file diff --git a/lib/layout/tree/samples/assets/file.png b/lib/layout/tree/samples/assets/file.png deleted file mode 100644 index 98bbf1298f239c39a43b364c79c7da1e52b99287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 609 zcmV-n0-pVeP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00GfSL_t(IPnDBdiyA=`Mu+4n!~9!+fZ(Hf z2qXyN4ldnj%cLJBcJNIw?S?3>gO&>#6-A*tDvHaOx;;!yg0mzAhc0?K_0_H0S66)a z{r=lzGRYE&ghf0aw}{1J_b!*~3!lHI_g) zcL&2Xuvjdhs;cK%fh0+6I2?j8CLkFJzN#u;_+d~IP18PINO-Z>cs#~nFc6T81WJOE zKMd0_EJ-Sr`uvw98jZ5qY-T-tgc4P&RmhSIzC}oX5DtgobUHr@3BSRX%O$4MsbDgh zpwsQ3R;!^{EJFXGBb&_%+-~;;#b5JT0QL28wZ=Fz~P_T}eFS-(f zU@*wm>or!Z)diG{ATia6j+^QeiA0t{5C{a=e!qulny*3&P%45K{z>5T`Pk`n!e+C1 z6-r54r7JJ&lfdisGCHQ+ZuchJ?H1?r8NB^31;^tNZ*e#rte#L5MF?*A&oUF;@{beV v)*D{L4^+q-o6S~mI2`yN>~{M-|MvPf5v#%NgV_W800000NkvXXu0mjfn)3vQ diff --git a/lib/layout/tree/samples/assets/folder-open.png b/lib/layout/tree/samples/assets/folder-open.png deleted file mode 100644 index ffd07a4865601705af5ee8a685fd09d60c728583..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 817 zcmV-11J3-3P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00N;&L_t(IPo-ECra{XgzX$cCN22Fatz7LwY(l6UCkS6VAb4d*S*IQR4m)`53wYRK z`@?B*{K{*!doRl7yQm6b8Txv=K{vdFsKbnRlOCvb9<-1AK(p43dW{p3?(Yz(Z7A)u zBEQvyY?Tq|jRwS58P!x7zXYu>o`EZBgSf{9PP+wZ&rP^Z2CmnC!{w*bI9EM^IN>-> z2*wc28wR^*7}0`>-%&Zb1nN<70VHB6?u#`Lb~$jT$$(o823%92koSmuOOcm#4gTt30Q#p-v)eKVVrjacBg2b9h#62EEY{>`?7Y-q^ zK#K#p0|>v@hdo>^!cyL6F|SdOlYy&+ZMa!)M3Qt0iPbusCc)@p63QRMLCyg7J?KYx zh6bUjy$DJDfE_n_oZI76L5zT#m4*w#AtcczoT-|^F~K<4C1W^LG=ly4TI|jqL|E1* zgrxU_byovcY9E46HOiO&LIAZbifi3@z8U@!l%R5N3_hDi1RDr}KG6|E%rdclp7)Zu vfR!H^P7b>WzI{Eu`buy0Oem>uC2aW%*(~qaPl}Ji00000NkvXXu0mjfdV6bJ diff --git a/lib/layout/tree/samples/assets/folder.png b/lib/layout/tree/samples/assets/folder.png deleted file mode 100644 index 17308c1edba308c00adf04f1accf8afd0341e942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 808 zcmV+@1K0eCP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+$tiu~XJ00NjvL_t(IPo;V+-ReDDiGf+WO}UB+XMnmhc+$sI>+AGM|uZ&w)ou zTvAA?8>OY=)gw4m?k(=T(T~W2K17w6Xr2l((glpVp&k(zTEN#@a8fafqgCXZvSGwZ zK44Gr0HO-}5Run|@ax?O%j!Z{{s_tIy@E^pRHml78X-v_l+JTLfKhN04w3+Y&WifgtVNa%pKP0uz)tp 0; - }, - fetchParent: function() { - return this.level > 0 && this.container.container; - }, - fetchChildren: function() { - return this.$.list && this.$.list.controls; - }, - fetchFirstChild: function() { - return this.$.list && this.$.list.controls[0]; - }, - fetchLastChild: function() { - return this.$.list && this.$.list.controls[this.$.list.controls.length-1]; - }, - fetchPrevSibling: function() { - var i = this.container.controls.indexOf(this); - return this.level > 0 && this.container.controls[i-1]; - }, - fetchNextSibling: function() { - var i = this.container.controls.indexOf(this); - return this.level > 0 && this.container.controls[i+1]; - }, - getVisibleBounds: function() { - return this.$.client.getBounds(); - } - */ -}); \ No newline at end of file diff --git a/lib/layout/tree/source/package.js b/lib/layout/tree/source/package.js deleted file mode 100644 index 5986bea..0000000 --- a/lib/layout/tree/source/package.js +++ /dev/null @@ -1,4 +0,0 @@ -enyo.depends( - "Node.css", - "Node.js" -); \ No newline at end of file diff --git a/lib/onyx/CONTRIBUTING md b/lib/onyx/CONTRIBUTING md deleted file mode 100644 index d0a3e5c..0000000 --- a/lib/onyx/CONTRIBUTING md +++ /dev/null @@ -1,44 +0,0 @@ -# Contributions - -Contributions are welcome for Enyo and its associated libraries including onyx and layout. - -Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details -on our contribution policy and guidelines for use of the Enyo-DCO-1.0-Signed-off-by -line in your commits and pull requests. - -If you're interested in introducing new kinds, you might also consider hosting your own repo -and contributing to the [Enyo community gallery](http://enyojs.com/gallery). - -## Modifications to CSS - -Onyx CSS is defined using parameterized LESS files. Whenever you make changes to LESS files in Onyx, you'll also need to re-generate and check-in the top-level .css file as well, to maintain backward-compatibility for environments that don't wish to use LESS. - -You can re-generate the top-level onyx.css file as follows: - - cd lib/onyx/css - ../../../enyo/tools/lessc.sh ./package.js - -NOTE: Since LESS generates relative URLs, it's important to run the `lessc.sh` script from the onyx css folder. - -Also note you only need to generate the .css file when you're ready to check in your changes. During development, you can do all your testing modifying just LESS files if you include "less-xyz.min.js" in your app's debug.html file, which compiles the LESS client-side during loading: - - - -Additionally, any new controls contributed should follow this basic pattern to ensure proper themability support: - -* Place control's .js file(s) in `lib/onyx/source` and add to `lib/onyx/source/package.js` -* Place control's .less file(s) in `lib/onyx/css` -* @import .less file(s) into [`lib/onyx/css/onyx-rules.less`](https://github.com/enyojs/onyx/blob/master/css/onyx-rules.less) -* Use existing variables from [`lib/onyx/css/onyx-variables.less`](https://github.com/enyojs/onyx/blob/master/css/onyx-variables.less) in your control's LESS files when available, add any new variables your particular control needs along with their default definitions to onyx-variables.less. - -Refer to the [UI Theming Guide](https://github.com/enyojs/enyo/wiki/UI-Theming) for more details. - -## Samples - -Every new control should be accompanied by at least one sample in the [Enyo 2 Sampler](http://enyojs.com/sampler). Read the [Sampler readme](https://github.com/enyojs/sampler) for details on how to go about adding new samples to the Sampler. - -Guidelines for samples: - -* Samples should live in a folder named `samples`, as a peer to the source -* Be sure to exercise useful API's and events of the control in the sample -* When one or more significantly different or interesting configurations of the control are available, include more than one instance in the sample to exhibit use of the different API's diff --git a/lib/onyx/LICENSE-2.0.txt b/lib/onyx/LICENSE-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/lib/onyx/LICENSE-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/lib/onyx/README.md b/lib/onyx/README.md deleted file mode 100644 index 9dc580e..0000000 --- a/lib/onyx/README.md +++ /dev/null @@ -1,29 +0,0 @@ -### Looking for the issue tracker? -It's moved to [https://enyojs.atlassian.net](https://enyojs.atlassian.net). - ---- - -## Onyx UI Library - -Onyx is a UI library for Enyo 2. - -We originally set out to adapt the Enyo 1 widgets for use with Enyo 2, but we quickly determined that we could achieve better cross-platform compatibility and build a more solid foundation for the future by starting with a clean slate. The result is a new UI library for Enyo 2 called **Onyx**. - -Despite the changes under the hood, you'll find that Onyx is clearly an evolution of the Enyo 1 UI from a design point of view. This first Onyx release features a variety of commonly used widgets, including toolbars, text inputs, checkboxes, groups and multiple types of buttons. Onyx also includes a base `Slideable` control that you can use to implement views that slide back and forth between pre-defined positions, including on and off screen. - -To get a feel for Onyx, check out the [OnyxSampler example](http://enyojs.com/samples/onyxsampler). Needless to say, we're not done -- we'll be expanding the Onyx widget set as we go. - -## Changes - -Any time you commit a change to a `.less` file, you also need to -re-generate the top-level library `.css` file as follows: - - cd lib/onyx/css - ../../enyo/tools/lessc.sh ./package.js - -This command will generate a new `onyx.css`, which you should check in -with your `.less` changes. - -Please don't manually edit the top-level `onyx.css`: those should be -treated as output files, and we should only be making changes to -`.less` files and generating the `.css` file using the above command. diff --git a/lib/onyx/css/Button.less b/lib/onyx/css/Button.less deleted file mode 100644 index c9d6f87..0000000 --- a/lib/onyx/css/Button.less +++ /dev/null @@ -1,71 +0,0 @@ -/* Button.css */ -.onyx-button { - outline: 0; - /**/ - color: @onyx-button-text-color; - font-size: @onyx-button-font-size; - text-align: center; - white-space: nowrap; - /**/ - margin: 0; - padding: @onyx-button-padding-tb @onyx-button-padding-lr; - overflow: hidden; - /**/ - border-radius: @onyx-button-border-radius; - /* for IE8 */ - border: 1px solid (@onyx-button-background * 0.498); - border: 1px solid fade((@onyx-button-background * 0.067), 20%); - /* - The border and the gradient interact in a strange way that - causes the bottom-border (top if the gradient is aligned top) - to be lighter than other borders. - We can fix it by using the darker bottom border below, but - then there are a few rogue pixels that end up very dark. - */ - /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ - box-shadow: inset 0px 1px 0px rgba(255,255,255,0.2); - /**/ - background: @onyx-button-background @onyx-button-gradient repeat-x bottom; - background-size: contain; - /**/ - text-overflow: ellipsis; - /* the following cause arcane problems on IE */ - /* - min-width: 14px; - min-height: 20px; - */ -} - -/* - IE8 can't handle these selectors in tandem: - .onyx-button.active, .onyx-button:active:not([disabled]) { - - the effect is as if .onyx-button.active doesn't exist -*/ -.onyx-button.active, .onyx-button.pressed { - background-image: @onyx-button-active-gradient; - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0,0,0,0.1); -} - -.onyx-button:active:hover:not([disabled]) { - background-image: @onyx-button-active-gradient; - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0,0,0,0.1); -} - -.onyx-button[disabled] { - opacity: @onyx-disabled-opacity; - filter: alpha(opacity=@onyx-disabled-opacity-ie); -} - -.onyx-button > img { - padding: 0px 3px; -} - -/* Remove the focused inner-border style in Firefox (Windows) */ -.onyx-button::-moz-focus-inner { - border: 0; -} \ No newline at end of file diff --git a/lib/onyx/css/ButtonColors.less b/lib/onyx/css/ButtonColors.less deleted file mode 100644 index f7ae783..0000000 --- a/lib/onyx/css/ButtonColors.less +++ /dev/null @@ -1,25 +0,0 @@ -/* ButtonColors.css */ -.onyx-button.onyx-blue { - background-color: #35A8EE; - color: #F2F2F2; -} - -.onyx-button.onyx-affirmative { - background-color: #91BA07; - color: #F2F2F2; -} - -.onyx-button.onyx-negative { - background-color: #C51616; - color: #F2F2F2; -} - -.onyx-button.onyx-dark { - background-color: @onyx-dark-background; - color: #F2F2F2; -} - -.onyx-button.onyx-light { - background-color: @onyx-light-background; - color: #2F2F2F; -} \ No newline at end of file diff --git a/lib/onyx/css/Checkbox.less b/lib/onyx/css/Checkbox.less deleted file mode 100644 index dea796c..0000000 --- a/lib/onyx/css/Checkbox.less +++ /dev/null @@ -1,20 +0,0 @@ -/* Checkbox.css */ -.onyx-checkbox { - cursor: pointer; - height: @onyx-checkbox-image-height; - width: @onyx-checkbox-image-width; - background: @onyx-checkbox-image no-repeat; - /* reset for ? */ - margin: 0px; - /* these entries cause toggle-button and checkbox to line up properly*/ - display: inline-block; - vertical-align: middle; -} - -.onyx-checkbox[checked] { - background-position: 0px -@onyx-checkbox-image-height; -} - -.onyx-checkbox[disabled] { - opacity: @onyx-disabled-opacity; -} diff --git a/lib/onyx/css/ContextualPopup.less b/lib/onyx/css/ContextualPopup.less deleted file mode 100644 index 9a1fdfb..0000000 --- a/lib/onyx/css/ContextualPopup.less +++ /dev/null @@ -1,230 +0,0 @@ -/* ContextualPopup.css */ -.onyx-contextual-popup-title { - font-weight:bold; - padding:24px 32px 0px; -} -.onyx-contextual-popup-scroller { - padding:24px 32px; -} -.onyx-contextual-popup-action-buttons { - display:inline-block; - width:100%; - text-align: center; -} -.onyx-contextual-popup-action-button { - margin-left: 5px; - margin-right: 5px; -} -.onyx-contextual-popup, -.onyx.onyx-contextual-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c; -} -/*setup the nub*/ -.onyx-contextual-popup::after{ - content: ''; - position: absolute; - top: -10px; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; -} -/*for popups above activator*/ -.onyx-contextual-popup.vertical.above { - top: auto; - margin-top:-10px; - bottom: 100%; - margin-bottom: 10px; -} -/*for popups below activator*/ -.onyx-contextual-popup.vertical.below { - margin-top:10px; -} -/*for popups on the left of the activator*/ -.onyx-contextual-popup.right.horizontal { - margin-left: -11px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.left.horizontal { - margin-left: 10px; -} -/*nub positioning*/ -/*horizontally centered nub*/ -.onyx-contextual-popup.vertical::after { - position:absolute; - left:45%; - border-bottom: 10px solid #4c4c4c; - border-top: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -/*nub near horizontal left*/ -.onyx-contextual-popup.vertical.right::after { - left:0%; - margin-left:20px; -} -/*nub near horizontal right*/ -.onyx-contextual-popup.vertical.left::after { - left:100%; - margin-left: -55px; -} -/*downward facing nub*/ -.onyx-contextual-popup.vertical.above::after { - top:100%; - border-top: 10px solid #4c4c4c; - border-bottom: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right::after { - top:0%; - margin-top:-10px; - border-bottom: 10px solid #4c4c4c; - border-left: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.left::after { - top:0%; - margin-top:-10px; - border-right: 10px solid transparent; -} -/*nub positioning for left/right popups*/ -/*vertically centered nub for popups on left of activator*/ -.onyx-contextual-popup.right::after { - left: 100%; - top:47%; - margin-right:20px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on left of activator*/ -.onyx-contextual-popup.right.high::after { - top: 35px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on left of activator*/ -.onyx-contextual-popup.right.low::after { - top:100%; - margin-top: -55px; - border-left: 10px solid #4C4C4C; -} -/*vertically centered nub for popups on right of activator*/ -.onyx-contextual-popup.left::after { - left: 0%; - margin-left: -20px; - top: 45%; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on right of activator*/ -.onyx-contextual-popup.left.high::after { - top: 35px; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on right of activator*/ -.onyx-contextual-popup.left.low::after { - top:100%; - margin-top: -55px; - border-right: 10px solid #4C4C4C; -} -/*corners*/ -/*vertical top corners*/ -/*for popups on the left of the activator*/ -.onyx-contextual-popup.vertical.right.corner { - margin-left: 0px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.vertical.left.corner { - margin-left: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.vertical.below.right.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner::after { - top:0%; - left:100%; - margin-top:-10px; - margin-left:-19px; - border-right: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right.corner::after { - top:0%; - left:0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -/*vertical bottom corners*/ -.onyx-contextual-popup.left.above.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.right.above.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.vertical.left.above.corner::after { - top:100%; - margin-left:-19px; - border-right: 10px solid #4C4C4C; - border-bottom: 10px solid transparent; - border-top: none; -} -.onyx-contextual-popup.vertical.right.above.corner::after { - top:100%; - left:0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-bottom: 10px solid transparent; - border-top: none; -} -/*horizontal bottom corners*/ -.onyx-contextual-popup.left.low.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.right.low.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.left.low.corner::after { - top:100%; - left:0%; - margin-top: -19px; - margin-left: -12px; - border-bottom: 10px solid #4c4c4c; - border-right: 10px solid #4c4c4c; -} -.onyx-contextual-popup.right.low.corner::after { - top:100%; - left:100%; - margin-top: -19px; - border-bottom: 10px solid#4c4c4c; - border-left: none; -} -/*horizontal top corners*/ -.onyx-contextual-popup.left.high.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.right.high.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.left.high.corner::after { - top:0%; - left:0%; - margin-top: -1px; - margin-left: -12px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -.onyx-contextual-popup.right.high.corner::after { - top:0%; - left:100%; - margin-top:-1px; - margin-left:-9px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} \ No newline at end of file diff --git a/lib/onyx/css/DatePicker.less b/lib/onyx/css/DatePicker.less deleted file mode 100644 index 3e4b282..0000000 --- a/lib/onyx/css/DatePicker.less +++ /dev/null @@ -1,14 +0,0 @@ -/* DatePicker.css */ -.onyx-datepicker-month { - min-width: 75px; -} - -.onyx-datepicker-day { - min-width: 60px; -} - -.onyx-datepicker-year { - min-width: 70px; -} - - diff --git a/lib/onyx/css/Grabber.less b/lib/onyx/css/Grabber.less deleted file mode 100644 index c44362f..0000000 --- a/lib/onyx/css/Grabber.less +++ /dev/null @@ -1,7 +0,0 @@ -/* Grabber.css */ -.onyx-grabber { - background: @onyx-grabber-image no-repeat center; - width: @onyx-grabber-image-width; - height: @onyx-grabber-image-height; -} - diff --git a/lib/onyx/css/Groupbox.less b/lib/onyx/css/Groupbox.less deleted file mode 100644 index 1195965..0000000 --- a/lib/onyx/css/Groupbox.less +++ /dev/null @@ -1,67 +0,0 @@ -/* Groupbox.css */ -.onyx-groupbox { -} - -.onyx-groupbox > * { - display: block; - /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ - border-color: #aaaaaa; - border-style: solid; - border-width: 0 1px 1px 1px; - /*padding: 10px;*/ - /* reset styles that make 'item' look bad if they happen to be there */ - border-radius: 0; - margin: 0; - font-size: @onyx-groupbox-font-size; -} - -.onyx-groupbox > *:first-child { - border-top-color: #aaaaaa; - border-width: 1px; - border-radius: @onyx-groupbox-border-radius @onyx-groupbox-border-radius 0 0; -} - -.onyx-groupbox > *:last-child { - border-radius: 0 0 @onyx-groupbox-border-radius @onyx-groupbox-border-radius; -} - -.onyx-groupbox > *:first-child:last-child { - border-radius: @onyx-groupbox-border-radius; -} - -.onyx-groupbox-header { - padding: 2px 10px; - /**/ - color: @onyx-groupbox-text-color; - font-size: @onyx-groupbox-header-font-size; - font-weight: bold; - text-transform: uppercase; - /**/ - background-color: @onyx-groupbox-background; - border: none; - background: @onyx-groupbox-background @onyx-groupbox-gradient repeat-x 0 10px; -} - -.onyx-groupbox .onyx-input-decorator { - display: block; -} - -.onyx-groupbox > .onyx-input-decorator { - border-color: #aaaaaa; - border-width: 0 1px 1px 1px; - border-radius: 0; -} - -.onyx-groupbox > .onyx-input-decorator:first-child { - border-width: 1px; - border-radius: @onyx-groupbox-border-radius @onyx-groupbox-border-radius 0 0; -} - -.onyx-groupbox > .onyx-input-decorator:last-child { - border-radius: 0 0 @onyx-groupbox-border-radius @onyx-groupbox-border-radius; -} - -.onyx-groupbox > .onyx-input-decorator:first-child:last-child { - border-radius: @onyx-groupbox-border-radius; -} - diff --git a/lib/onyx/css/Icon.less b/lib/onyx/css/Icon.less deleted file mode 100644 index c18e00b..0000000 --- a/lib/onyx/css/Icon.less +++ /dev/null @@ -1,21 +0,0 @@ -/* Icon.css */ -.onyx-icon, .onyx-icon-toggle { - width: @onyx-icon-size; - height: @onyx-icon-size; - background-repeat: no-repeat; - display: inline-block; - vertical-align: middle; -} - -.onyx-icon.onyx-icon-button.active, .onyx-icon.onyx-icon-button.pressed, .onyx-icon.onyx-icon-button:active:hover, .onyx-icon-toggle.active { - background-position: 0 -@onyx-icon-size; -} - -.onyx-icon.disabled { - opacity: @onyx-disabled-opacity; - filter: alpha(opacity=@onyx-disabled-opacity-ie); -} - -.onyx-icon.disabled:active:hover { - background-position: 0 0px; -} diff --git a/lib/onyx/css/Input.less b/lib/onyx/css/Input.less deleted file mode 100644 index f0d5162..0000000 --- a/lib/onyx/css/Input.less +++ /dev/null @@ -1,45 +0,0 @@ -/* Input.css */ -.onyx-input-decorator { - padding: 6px 8px 10px 8px; - border-radius: @onyx-input-border-radius; - border: 1px solid; - border-color: rgba(0,0,0,0.1); - margin: 0; -} - -.onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0,0,0,0.3); - border-color: rgba(0,0,0,0.3); - background-color: @onyx-input-focused-background; -} - -.onyx-input-decorator.onyx-disabled { - /* FIXME: needed to color a disabled input placeholder. */ - /*-webkit-text-fill-color: #888;*/ - opacity: @onyx-disabled-opacity; - filter: alpha(opacity=@onyx-disabled-opacity-ie); -} - -.onyx-input-decorator > input { - /* reset */ - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: @onyx-input-background; - background-image: none; - font-size: @onyx-input-font-size; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - /* -webkit-appearance: caret;*/ -} - -.onyx-input-decorator.onyx-focused > input { - cursor: text; -} - -.onyx-input-decorator.onyx-disabled > input { - cursor: default; -} - diff --git a/lib/onyx/css/Item.less b/lib/onyx/css/Item.less deleted file mode 100644 index 7b95026..0000000 --- a/lib/onyx/css/Item.less +++ /dev/null @@ -1,24 +0,0 @@ -/* Item.css */ -.onyx-item { - padding: 14px; -} - -.onyx-highlight, .onyx-highlight.onyx-swipeable-item-content { - background-color: @onyx-highlight-background; -} - -.enyo-selected, .enyo-selected.onyx-swipeable-item-content { - background-color: @onyx-selected-background; -} - -.onyx-item.onyx-swipeable-item { - overflow: hidden; - padding: 0; -} - -.onyx-swipeable-item-content { - background-color: @onyx-switeable-item-background; - box-sizing: border-box; - padding: 18px 6px; - min-height: 40px; -} diff --git a/lib/onyx/css/Menu.less b/lib/onyx/css/Menu.less deleted file mode 100644 index 8cb8118..0000000 --- a/lib/onyx/css/Menu.less +++ /dev/null @@ -1,64 +0,0 @@ -/* Menu.css */ -.onyx-menu, .onyx.onyx-menu { - min-width: 160px; - top: 100%; - left: 0; - margin-top: 2px; - padding: 3px 0; - border-radius: @onyx-menu-border-radius; -} - -.onyx-menu.onyx-menu-up { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 2px; -} - -.onyx-toolbar .onyx-menu { - margin-top: 11px; - border-radius: 0 0 @onyx-menu-border-radius @onyx-menu-border-radius; -} - - -.onyx-toolbar .onyx-menu.onyx-menu-up { - margin-top: 0; - margin-bottom: 10px; - border-radius: @onyx-menu-border-radius @onyx-menu-border-radius 0 0; -} - -.onyx-menu-item { - display: block; - padding: 10px; -} - -.onyx-menu-item:hover { - background: @onyx-menu-item-hover; -} - -.onyx-menu-divider, .onyx-menu-divider:hover { - margin: 6px 0; - padding: 0; - border-bottom: 1px solid #aaa; -} - -.onyx-menu-label { - cursor: default; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - opacity: @onyx-disabled-opacity; - filter: alpha(opacity=@onyx-disabled-opacity-ie); -} - -.onyx-menu-label:hover { - background: none; -} - -/* customize a toolbar to support menus */ -.onyx-menu-toolbar, .onyx-toolbar.onyx-menu-toolbar { - position: relative; - z-index: 10; - overflow: visible; -} - diff --git a/lib/onyx/css/MoreToolbar.less b/lib/onyx/css/MoreToolbar.less deleted file mode 100644 index 8084c93..0000000 --- a/lib/onyx/css/MoreToolbar.less +++ /dev/null @@ -1,30 +0,0 @@ -/* MoreToolbar.css */ -.onyx-more-toolbar { - overflow: visible; - position: relative; - z-index: 10; -} - -.onyx-more-toolbar.active { - z-index:11; -} - -.onyx-more-menu { - left: auto; - right: 0px; - min-width: 0; -} - -.onyx-more-toolbar .onyx-more-menu > * { - float: right; - clear: both; - margin: 5px; - margin-top: 5px; - margin-bottom: 5px; -} - -.onyx-more-button { - background-image: @onyx-more-toolbar-button-image; - width: @onyx-more-toolbar-button-image-width; - height: @onyx-more-toolbar-button-image-height; -} diff --git a/lib/onyx/css/Picker.less b/lib/onyx/css/Picker.less deleted file mode 100644 index 8a3d545..0000000 --- a/lib/onyx/css/Picker.less +++ /dev/null @@ -1,49 +0,0 @@ -/* Picker.css */ -.onyx-picker-decorator .onyx-button { - padding: 10px 18px; -} - -.onyx-picker { - top: 0; - margin-top: -3px; - min-width: 0; - width: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; - color: black; - background: @onyx-picker-background; -} - -.onyx-picker.onyx-menu-up { - top: auto; - bottom: 0; - margin-top: 3px; - margin-bottom: -3px; -} - -.onyx-picker .onyx-menu-item { - text-align: center; -} - -.onyx-picker .onyx-menu-item:hover { - background-color: transparent; -} - -.onyx-picker .onyx-menu-item.selected, .onyx-picker .onyx-menu-item.active, .onyx-picker .onyx-menu-item:active:hover { - border-top: 1px solid rgba(0, 0, 0, 0.1); - background-color: @onyx-picker-item-background; - box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); -} - -.onyx-picker .onyx-menu-item { - border-top: 1px solid rgba(255,255,255,0.5); - border-bottom: 1px solid rgba(0,0,0,0.2); -} - -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, .onyx-flyweight-picker :first-child > .onyx-menu-item { - border-top: none; -} - -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, .onyx-flyweight-picker :last-child > .onyx-menu-item { - border-bottom: none; -} diff --git a/lib/onyx/css/Popup.less b/lib/onyx/css/Popup.less deleted file mode 100644 index 7ed22ce..0000000 --- a/lib/onyx/css/Popup.less +++ /dev/null @@ -1,14 +0,0 @@ -/* Popup.css */ -.onyx-popup { - font-size: @onyx-popup-font-size; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0,0,0,0.2); - border-radius: 8px; - padding: 6px; - color: @onyx-popup-text-color; - background: @onyx-popup-background @onyx-button-gradient repeat-x 0 bottom; -} - -.onyx-popup-decorator { - position: relative; -} diff --git a/lib/onyx/css/ProgressBar.less b/lib/onyx/css/ProgressBar.less deleted file mode 100644 index f3c7c72..0000000 --- a/lib/onyx/css/ProgressBar.less +++ /dev/null @@ -1,69 +0,0 @@ -/* ProgressBar.css */ -.onyx-progress-bar { - margin: 8px; - height: 8px; - border: 1px solid rgba(15, 15, 15, 0.2); - border-radius: @onyx-progressbar-border-radius; - background: @onyx-progressbar-background @onyx-progressbar-gradient repeat-x; - background-size: auto 100%; -} - -.onyx-progress-bar-bar { - height: 100%; - border-radius: @onyx-progressbar-border-radius; - background: @onyx-progressbar-bar-background @onyx-progressbar-bar-gradient repeat-x; - background-size: auto 100%; -} - -.onyx-progress-bar-bar.striped { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} - -.onyx-progress-bar-bar.striped.animated { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} diff --git a/lib/onyx/css/ProgressButton.less b/lib/onyx/css/ProgressButton.less deleted file mode 100644 index ace04d3..0000000 --- a/lib/onyx/css/ProgressButton.less +++ /dev/null @@ -1,33 +0,0 @@ -/* ProgressButton.css */ -.onyx-progress-button { - position: relative; - height: 36px; - line-height: 36px; - color: @onyx-progressbutton-text-color; - font-size: @onyx-progressbutton-font-size; - text-overflow: ellipsis; -} - -.onyx-progress-button-bar { - height: 36px; -} - -.onyx-progress-button-icon { - display: inline-block; - position: absolute; - top: 2px; - right: 0; -} - -.onyx-progress-button-client { - display: inline-block; - position: absolute; - top: 0; - left: 0; - right: 36px; - margin-left: 8px; -} - -.onyx-progress-button-client > * { - display: inline-block; -} diff --git a/lib/onyx/css/RadioButton.less b/lib/onyx/css/RadioButton.less deleted file mode 100644 index fb23e4f..0000000 --- a/lib/onyx/css/RadioButton.less +++ /dev/null @@ -1,37 +0,0 @@ -/* RadioButton.css */ -.onyx-radiobutton { - padding: 8px 12px; - margin: 0; - outline: 0; - /**/ - font-size: @onyx-radiobutton-font-size; - text-shadow: 0 1px 1px rgba(0,0,0,0.2); - text-align: center; - /**/ - background: @onyx-radiobutton-background @onyx-radiobutton-gradient repeat-x bottom; - /* IE8 */ - border: 1px solid (@onyx-radiobutton-background * 0.22); - border: 1px solid fade((@onyx-radiobutton-background * 0.065), 20%); - /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ - border-right-color: rgba(0,0,0,0); - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); -} - -.onyx-radiobutton:first-child { - border-radius: @onyx-radiobutton-border-radius 0 0 @onyx-radiobutton-border-radius; -} - -.onyx-radiobutton:last-child { - border-radius: 0px @onyx-radiobutton-border-radius @onyx-radiobutton-border-radius 0px; - /* IE8 */ - border-right: 1px solid (@onyx-radiobutton-background * 0.22); - border-right: 1px solid fade((@onyx-radiobutton-background * 0.065), 20%); -} - -.onyx-radiobutton.active { - color: @onyx-radiobutton-active-text-color; - background: @onyx-radiobutton-active-background @onyx-gradient-invert repeat-x top; - border-top: 1px solid fade((@onyx-radiobutton-background * 0.065), 60%); - box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); -} - diff --git a/lib/onyx/css/RangeSlider.less b/lib/onyx/css/RangeSlider.less deleted file mode 100644 index 4a556f9..0000000 --- a/lib/onyx/css/RangeSlider.less +++ /dev/null @@ -1,10 +0,0 @@ -/* RangeSlider.css */ -.onyx-range-slider-knob { - top: -17px; -} -.onyx-range-slider-label { - position: relative; - top: -18px; - text-align: center; - white-space: nowrap; -} diff --git a/lib/onyx/css/RichText.less b/lib/onyx/css/RichText.less deleted file mode 100644 index e0e1492..0000000 --- a/lib/onyx/css/RichText.less +++ /dev/null @@ -1,26 +0,0 @@ -/* RichText.css */ -.onyx-input-decorator > .onyx-richtext { - /* reset */ - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: @onyx-input-background; - background-image: none; - font-size: @onyx-richtext-font-size; - min-height: 20px; - min-width: 100px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - /* -webkit-appearance: caret;*/ -} - -.onyx-input-decorator.onyx-focused > .onyx-richtext { - cursor: text; -} - -.onyx-input-decorator.onyx-disabled > .onyx-richtext { - cursor: default; -} - diff --git a/lib/onyx/css/Scrim.less b/lib/onyx/css/Scrim.less deleted file mode 100644 index 06b041a..0000000 --- a/lib/onyx/css/Scrim.less +++ /dev/null @@ -1,23 +0,0 @@ -/* Scrim.css */ -.onyx-scrim { - z-index: 1; - /* - note: by using pointer-events we allow tapping on scrim - while it is fading out; however, this requires any showing classes - to set pointer events to auto or scrim will not function as expected. - */ - pointer-events: none; -} - -@onyx-scrim-opacity-ie: @onyx-scrim-opacity*100; -.onyx-scrim.onyx-scrim-translucent{ - pointer-events: auto; - background-color: @onyx-scrim-background; - opacity: @onyx-scrim-opacity; - filter: alpha(opacity=@onyx-scrim-opacity-ie); -} - -.onyx-scrim.onyx-scrim-transparent { - pointer-events: auto; - background: transparent; -} diff --git a/lib/onyx/css/Slider.less b/lib/onyx/css/Slider.less deleted file mode 100644 index ff33960..0000000 --- a/lib/onyx/css/Slider.less +++ /dev/null @@ -1,24 +0,0 @@ -/* Slider.css */ -.onyx-slider { - position: relative; - margin: 8px 20px; -} - -.onyx-slider-taparea { - position: absolute; - top: -11px; - height: 28px; - width: 100%; -} - -.onyx-slider-knob { - position: relative; - height: @onyx-slider-knob-image-height; - width: @onyx-slider-knob-image-width; - background: @onyx-slider-knob-image left top no-repeat; - margin: -23px -20px; -} - -.onyx-slider-knob.active, .onyx-slider-knob.pressed, .onyx-slider-knob:active:hover { - background-position: 0 -40px; -} diff --git a/lib/onyx/css/Spinner.less b/lib/onyx/css/Spinner.less deleted file mode 100644 index 225a5dd..0000000 --- a/lib/onyx/css/Spinner.less +++ /dev/null @@ -1,11 +0,0 @@ -/* Spinner.css */ -.onyx-spinner { - width: @onyx-spinner-image-width; - height: @onyx-spinner-image-height; - display: inline-block; - background: @onyx-spinner-dark-image no-repeat 0 0; -} - -.onyx-spinner.onyx-light { - background: @onyx-spinner-light-image no-repeat 0 0; -} diff --git a/lib/onyx/css/TabButton.less b/lib/onyx/css/TabButton.less deleted file mode 100644 index 7858b27..0000000 --- a/lib/onyx/css/TabButton.less +++ /dev/null @@ -1,7 +0,0 @@ -/* TabButton.css */ -.onyx-radiobutton.onyx-tabbutton { - padding: @onyx-tabbutton-padding-tb @onyx-tabbutton-padding-lr; - font-size: @onyx-tabbutton-font-size; - border-radius: 0px; -} - diff --git a/lib/onyx/css/TextArea.less b/lib/onyx/css/TextArea.less deleted file mode 100644 index c6fa115..0000000 --- a/lib/onyx/css/TextArea.less +++ /dev/null @@ -1,32 +0,0 @@ -/* TextArea.css */ -.onyx-input-decorator > textarea { - /* reset */ - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: @onyx-input-background; - background-image: none; - font-size: @onyx-textarea-font-size; - box-shadow: none; - /* Remove scrollbars and resize handle */ - resize: none; - overflow: auto; - /* FIXME: hack for styling reset on Android */ - /* -webkit-appearance: caret;*/ -} - -.onyx-input-decorator.onyx-focused > textarea { - cursor: text; -} - -.onyx-input-decorator.onyx-disabled > textarea { - cursor: default; -} - -.onyx-textarea { - /* need >=50px for scrollbar to be usable on mac */ - min-height: 50px; -} - diff --git a/lib/onyx/css/TimePicker.less b/lib/onyx/css/TimePicker.less deleted file mode 100644 index a3a973c..0000000 --- a/lib/onyx/css/TimePicker.less +++ /dev/null @@ -1,12 +0,0 @@ -/* TimePicker.css */ -.onyx-timepicker-hour { - min-width: 60px; -} - -.onyx-timepicker-minute { - min-width: 60px; -} - -.onyx-timepicker-ampm { - min-width: 60px; -} \ No newline at end of file diff --git a/lib/onyx/css/ToggleButton.less b/lib/onyx/css/ToggleButton.less deleted file mode 100644 index c297d71..0000000 --- a/lib/onyx/css/ToggleButton.less +++ /dev/null @@ -1,65 +0,0 @@ -/* ToggleButton.css */ -.onyx-toggle-button { - display: inline-block; - height: 32px; - line-height: 32px; - min-width: 64px; - vertical-align: middle; - text-align: center; - /* */ - border-radius: @onyx-togglebutton-border-radius; - box-shadow: inset 0px 1px 3px rgba(0,0,0,0.4); - background: @onyx-togglebutton-background @onyx-togglebutton-gradient repeat-x bottom; - background-size: auto 100%; - /* label */ - color: @onyx-togglebutton-text-color; - font-size: @onyx-togglebutton-font-size; - font-weight: bold; - text-transform: uppercase; -} - -.onyx-toggle-button.off { - background-color: @onyx-togglebutton-off-background !important; -} - -.onyx-toggle-button-knob { - display: inline-block; - width: 30px; - height: 30px; - margin: 1px; - border-radius: @onyx-togglebutton-border-radius; - background: @onyx-togglebutton-knob-background @onyx-togglebutton-knob-gradient repeat-x; - background-size: auto 100%; -} - -.onyx-toggle-button .onyx-toggle-button-knob { - box-shadow: -1px 0px 4px rgba(0,0,0,0.35), inset 0 -1px 0 rgba(0,0,0,0.4); - float: right; -} - -.onyx-toggle-button.off .onyx-toggle-button-knob { - box-shadow: 1px 0px 4px rgba(0,0,0,0.35), inset 0 -1px 0 rgba(0,0,0,0.4); - float: left; -} - -.onyx-toggle-button.disabled, .onyx-icon-button.disabled { - opacity: @onyx-disabled-opacity; - filter: alpha(opacity=@onyx-disabled-opacity-ie); -} - -.onyx-toggle-content { - min-width: 32px; - padding: 0 6px; -} - -.onyx-toggle-content.empty { - padding: 0; -} - -.onyx-toggle-content.off { - float: right; -} - -.onyx-toggle-content.on { - float: left; -} diff --git a/lib/onyx/css/Toolbar.less b/lib/onyx/css/Toolbar.less deleted file mode 100644 index 1e0448c..0000000 --- a/lib/onyx/css/Toolbar.less +++ /dev/null @@ -1,64 +0,0 @@ -/* Toolbar.css */ -.onyx-toolbar { - /* - line-height is unreliable for centering, instead - use vertical-align: middle to align - elements along a common centerline and use - padding to fill out the space. - */ - padding: 9px 8px 10px 8px; - /**/ - border: 1px solid #3A3A3A; - background: @onyx-toolbar-background @onyx-toolbar-gradient repeat-x 0 bottom; - background-size: contain; - color: @onyx-toolbar-text-color; - /**/ - white-space: nowrap; - overflow-y: visible; - font-size: @onyx-toolbar-font-size; -} - -.onyx-toolbar-inline > *, .enyo-fittable-columns-layout.onyx-toolbar-inline > * { - display: inline-block; - vertical-align: middle; - margin: 4px 6px 5px; - box-sizing: border-box; -} - -.onyx-toolbar .onyx-icon-button { - margin: 3px 2px 1px; -} - -.onyx-toolbar .onyx-button { - color: @onyx-toolbar-button-text-color; - background-color: @onyx-toolbar-button-background; - border-color: rgba(15, 15, 15, 0.5); - margin-top: 0; - margin-bottom: 0; - height: 36px; -} - -.onyx-toolbar .onyx-input-decorator { - margin: 1px 3px; - box-shadow: inset 0px 1px 4px rgba(0,0,0,0.1); - background-color: @onyx-toolbar-input-background; - padding: 0px 6px 5px 6px; -} - -.onyx-toolbar .onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0,0,0,0.3); - background-color: @onyx-toolbar-input-focused-background; -} - -.onyx-toolbar .onyx-input-decorator .onyx-input { - color: @onyx-toolbar-input-text-color; - font-size: @onyx-toolbar-input-font-size; -} - -.onyx-toolbar .onyx-input-decorator .onyx-input:focus { - color: @onyx-toolbar-input-focus-text-color; -} - -.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { - color: @onyx-toolbar-input-placeholder-text-color; -} diff --git a/lib/onyx/css/Tooltip.less b/lib/onyx/css/Tooltip.less deleted file mode 100644 index d4925b8..0000000 --- a/lib/onyx/css/Tooltip.less +++ /dev/null @@ -1,70 +0,0 @@ -/* Tooltip.css */ -.onyx-tooltip { - z-index: 20; - left: 0; - padding: 4px 6px; - margin-top: 4px; - margin-left: -6px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0,0,0,0.2); - color: @onyx-tooltip-text-color; - background: @onyx-tooltip-background @onyx-tooltip-gradient repeat-x 0 bottom; - border-radius: @onyx-tooltip-border-radius; - white-space: nowrap; -} - -/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ -.onyx-tooltip.right-arrow { - left: 30px; -} - -/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ -.onyx-tooltip::before { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - left: 16px; -} - -.onyx-tooltip::after { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - margin-left: -12px; -} - -/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ -.onyx-tooltip.below { - top: 100%; -} - -.onyx-tooltip.below.right-arrow::after { - border-bottom: 6px solid #1D587F; - top: -6px; -} - -.onyx-tooltip.below.left-arrow::before { - border-bottom: 6px solid #1D587F; - top: -6px; -} - -/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ -.onyx-tooltip.above { - top: -100%; -} - -.onyx-tooltip.above.right-arrow::after { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} - -.onyx-tooltip.above.left-arrow::before { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} \ No newline at end of file diff --git a/lib/onyx/css/onyx-rules.less b/lib/onyx/css/onyx-rules.less deleted file mode 100644 index 1b33f4a..0000000 --- a/lib/onyx/css/onyx-rules.less +++ /dev/null @@ -1,78 +0,0 @@ -/* onyx-classes.less - combined CSS (less) files for all released Onyx controls - into single onyx.less file to avoid IE bug that allows - a maximum of 31 style sheets to be loaded before silently failing */ - -.onyx { - color: @onyx-text-color; - font-family: @onyx-font-family; - font-size: @onyx-font-size; - cursor: default; - background-color: @onyx-background; - /* remove automatic tap highlight color */ - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -/* prevent IE from inheriting line-height for these elements */ -.onyx button, .onyx label, .onyx input { - line-height: normal; -} - -.onyx-selected { - background-color: @onyx-selected-background; -} - -/* LESS pre-calculations */ -@onyx-disabled-opacity-ie: @onyx-disabled-opacity*100; - - -/* Individual Widget CSS */ - -@import "Icon.less"; -@import "Button.less"; -@import "Checkbox.less"; -@import "Grabber.less"; -@import "Popup.less"; -@import "Groupbox.less"; -@import "Input.less"; -@import "Menu.less"; -@import "Picker.less"; -@import "TextArea.less"; -@import "RichText.less"; -@import "RadioButton.less"; -@import "Scrim.less"; -@import "TabButton.less"; -@import "ToggleButton.less"; -@import "Toolbar.less"; -@import "Tooltip.less"; -@import "ProgressBar.less"; -@import "ProgressButton.less"; -@import "Slider.less"; -@import "RangeSlider.less"; -@import "Item.less"; -@import "Spinner.less"; -@import "MoreToolbar.less"; -@import "DatePicker.less"; -@import "TimePicker.less"; -@import "ButtonColors.less"; -@import "ContextualPopup.less"; - -/* some default colors */ -.onyx-dark { - background-color: @onyx-dark-background; -} - -.onyx-light { - background-color: @onyx-light-background; -} - -.onyx-green { - background-color: #91BA07; -} - -.onyx-red { - background-color: #C51616; -} - -.onyx-blue { - background-color: #35A8EE; -} \ No newline at end of file diff --git a/lib/onyx/css/onyx-variables.less b/lib/onyx/css/onyx-variables.less deleted file mode 100644 index 2add963..0000000 --- a/lib/onyx/css/onyx-variables.less +++ /dev/null @@ -1,140 +0,0 @@ -/* Fonts */ -/* ---------------------------------------*/ -@onyx-font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; -@onyx-font-size-small: 14px; -@onyx-font-size-medium: 16px; -@onyx-font-size-large: 20px; - -@onyx-button-font-size: @onyx-font-size-medium; -@onyx-font-size: @onyx-font-size-large; -@onyx-groupbox-font-size: @onyx-font-size-medium; -@onyx-groupbox-header-font-size: @onyx-font-size-small; -@onyx-input-font-size: @onyx-font-size-medium; -@onyx-popup-font-size: @onyx-font-size-medium; -@onyx-progressbutton-font-size: @onyx-font-size-medium; -@onyx-radiobutton-font-size: @onyx-font-size-medium; -@onyx-richtext-font-size: @onyx-font-size-medium; -@onyx-tabbutton-font-size: @onyx-font-size-large; -@onyx-textarea-font-size: @onyx-font-size-medium; -@onyx-togglebutton-font-size: @onyx-font-size-small; -@onyx-toolbar-font-size: @onyx-font-size-large; -@onyx-toolbar-input-font-size: @onyx-font-size-small; - -/* Text Colors */ -/* ---------------------------------------*/ -@onyx-button-text-color: #292929; -@onyx-groupbox-text-color: white; -@onyx-picker-text-color: black; -@onyx-popup-text-color: white; -@onyx-progressbutton-text-color: #F1F1F1; -@onyx-radiobutton-active-text-color: white; -@onyx-text-color: #333333; -@onyx-togglebutton-text-color: white; -@onyx-toolbar-button-text-color: #F2F2F2; -@onyx-toolbar-input-focus-text-color: #000; -@onyx-toolbar-input-placeholder-text-color: #ddd; -@onyx-toolbar-input-text-color: #e5e5e5; -@onyx-toolbar-text-color: white; -@onyx-tooltip-text-color: white; - -/* Background Colors */ -/* ---------------------------------------*/ -@onyx-background: #EAEAEA; -@onyx-light-background: #CACACA; -@onyx-dark-background: #555656; -@onyx-selected-background: #C4E3FE; - -@onyx-button-background: #E1E1E1; -@onyx-groupbox-background: #4C4C4C; -@onyx-highlight-background: #DEDFDF; -@onyx-input-background: transparent; -@onyx-input-focused-background: white; -@onyx-menu-item-hover: #284152; -@onyx-picker-background: #E1E1E1; -@onyx-picker-item-background: #cde7fe; -@onyx-popup-background: #4C4C4C; -@onyx-progressbar-background: #B8B8B8; -@onyx-progressbar-bar-background: #58ABEF; -@onyx-radiobutton-active-background: #0091F2; -@onyx-radiobutton-background: #E7E7E7; -@onyx-scrim-background: black; -@onyx-scrim-opacity: 0.65; -@onyx-switeable-item-background: #EAEAEA; -@onyx-togglebutton-background: #8BBA3D; -@onyx-togglebutton-knob-background: #F6F6F6; -@onyx-togglebutton-off-background: #B1B1B1; -@onyx-toolbar-background: #4C4C4C; -@onyx-toolbar-button-background: #555656; -@onyx-toolbar-input-background: rgba(0, 0, 0, 0.1); -@onyx-toolbar-input-focused-background: white; -@onyx-tooltip-background: #216593; - -/* Border Radius */ -/* ---------------------------------------*/ -@onyx-border-radius: 4px; -@onyx-border-radius-tight: 3px; - -@onyx-button-border-radius: @onyx-border-radius-tight; -@onyx-groupbox-border-radius: @onyx-border-radius; -@onyx-input-border-radius: @onyx-border-radius-tight; -@onyx-menu-border-radius: @onyx-border-radius-tight; -@onyx-progressbar-border-radius: @onyx-border-radius-tight; -@onyx-radiobutton-border-radius: @onyx-border-radius-tight; -@onyx-togglebutton-border-radius: @onyx-border-radius-tight; -@onyx-tooltip-border-radius: @onyx-border-radius-tight; - -/* Padding */ -/* ---------------------------------------*/ -@onyx-button-padding-lr: 18px; -@onyx-button-padding-tb: 6px; -@onyx-tabbutton-padding-lr: 34px; -@onyx-tabbutton-padding-tb: 8px; - -/* Icon Sizes */ -/* ---------------------------------------*/ -@onyx-icon-size: 32px; - -/* Disabled Opacity */ -/* ---------------------------------------*/ -@onyx-disabled-opacity: 0.4; - -/* Gradient Overlays */ -/* ---------------------------------------*/ -@onyx-gradient: url(../images/gradient.png); -@onyx-gradient-invert: url(../images/gradient-invert.png); - -@onyx-button-active-gradient: @onyx-gradient-invert; -@onyx-button-gradient: @onyx-gradient; -@onyx-groupbox-gradient: @onyx-gradient; -@onyx-popup-gradient: @onyx-gradient; -@onyx-progressbar-bar-gradient: @onyx-gradient; -@onyx-progressbar-gradient: @onyx-gradient-invert; -@onyx-radiobutton-active-gradient: @onyx-gradient-invert; -@onyx-radiobutton-gradient: @onyx-gradient; -@onyx-togglebutton-gradient: @onyx-gradient-invert; -@onyx-togglebutton-knob-gradient: @onyx-gradient; -@onyx-toolbar-gradient: @onyx-gradient; -@onyx-tooltip-gradient: @onyx-gradient; - -/* Images */ -/* ---------------------------------------*/ -@onyx-checkbox-image: url(../images/checkbox.png); -@onyx-checkbox-image-height: 32px; -@onyx-checkbox-image-width: 32px; - -@onyx-grabber-image: url(../images/grabbutton.png); -@onyx-grabber-image-height: 27px; -@onyx-grabber-image-width: 23px; - -@onyx-more-toolbar-button-image: url(../images/more.png); -@onyx-more-toolbar-button-image-height: 32px; -@onyx-more-toolbar-button-image-width: 32px; - -@onyx-slider-knob-image: url(../images/slider-handle.png); -@onyx-slider-knob-image-height: 40px; -@onyx-slider-knob-image-width: 40px; - -@onyx-spinner-dark-image: url(../images/spinner-dark.gif); -@onyx-spinner-light-image: url(../images/spinner-light.gif); -@onyx-spinner-image-width: 59px; -@onyx-spinner-image-height: 58px; diff --git a/lib/onyx/css/onyx.css b/lib/onyx/css/onyx.css deleted file mode 100644 index c2b3519..0000000 --- a/lib/onyx/css/onyx.css +++ /dev/null @@ -1,1153 +0,0 @@ -/* WARNING: This is a generated file for backward-compatibility. Most */ -/* usrs should instead modify LESS files. If you choose to edit this CSS */ -/* directly rather than LESS files, you should make sure less.xx.yy.min.js */ -/* is commented out in your debug.html, and run deploy.sh/bat using the */ -/* '-c' flag to disable LESS compilation. This will force the loader and */ -/* minifier to fall back to using CSS files in place of the same-name */ -/* LESS file. */ - -/* Onyx default parameters defined here */ -/* Fonts */ -/* ---------------------------------------*/ -/* Text Colors */ -/* ---------------------------------------*/ -/* Background Colors */ -/* ---------------------------------------*/ -/* Border Radius */ -/* ---------------------------------------*/ -/* Padding */ -/* ---------------------------------------*/ -/* Icon Sizes */ -/* ---------------------------------------*/ -/* Disabled Opacity */ -/* ---------------------------------------*/ -/* Gradient Overlays */ -/* ---------------------------------------*/ -/* Images */ -/* ---------------------------------------*/ -/* Onyx rules defined here */ -/* onyx-classes.less - combined CSS (less) files for all released Onyx controls - into single onyx.less file to avoid IE bug that allows - a maximum of 31 style sheets to be loaded before silently failing */ -.onyx { - color: #333333; - font-family: 'Helvetica Neue', 'Nimbus Sans L', Arial, sans-serif; - font-size: 20px; - cursor: default; - background-color: #eaeaea; - /* remove automatic tap highlight color */ - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -/* prevent IE from inheriting line-height for these elements */ -.onyx button, -.onyx label, -.onyx input { - line-height: normal; -} -.onyx-selected { - background-color: #c4e3fe; -} -/* LESS pre-calculations */ -/* Individual Widget CSS */ -/* Icon.css */ -.onyx-icon, -.onyx-icon-toggle { - width: 32px; - height: 32px; - background-repeat: no-repeat; - display: inline-block; - vertical-align: middle; -} -.onyx-icon.onyx-icon-button.active, -.onyx-icon.onyx-icon-button.pressed, -.onyx-icon.onyx-icon-button:active:hover, -.onyx-icon-toggle.active { - background-position: 0 -32px; -} -.onyx-icon.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-icon.disabled:active:hover { - background-position: 0 0px; -} -/* Button.css */ -.onyx-button { - outline: 0; - color: #292929; - font-size: 16px; - text-align: center; - white-space: nowrap; - margin: 0; - padding: 6px 18px; - overflow: hidden; - border-radius: 3px; - /* for IE8 */ - - border: 1px solid #707070; - border: 1px solid rgba(15, 15, 15, 0.2); - /* - The border and the gradient interact in a strange way that - causes the bottom-border (top if the gradient is aligned top) - to be lighter than other borders. - We can fix it by using the darker bottom border below, but - then there are a few rogue pixels that end up very dark. - */ - - /* border-bottom: 1px solid rgba(15, 15, 15, 0.5); */ - - box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.2); - background: #e1e1e1 url(./../images/gradient.png) repeat-x bottom; - background-size: contain; - /**/ - - text-overflow: ellipsis; - /* the following cause arcane problems on IE */ - - /* - min-width: 14px; - min-height: 20px; - */ - -} -/* - IE8 can't handle these selectors in tandem: - .onyx-button.active, .onyx-button:active:not([disabled]) { - - the effect is as if .onyx-button.active doesn't exist -*/ -.onyx-button.active, -.onyx-button.pressed { - background-image: url(./../images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button:active:hover:not([disabled]) { - background-image: url(./../images/gradient-invert.png); - background-position: top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1); -} -.onyx-button[disabled] { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-button > img { - padding: 0px 3px; -} -/* Remove the focused inner-border style in Firefox (Windows) */ -.onyx-button::-moz-focus-inner { - border: 0; -} -/* Checkbox.css */ -.onyx-checkbox { - cursor: pointer; - height: 32px; - width: 32px; - background: url(./../images/checkbox.png) no-repeat; - /* reset for ? */ - - margin: 0px; - /* these entries cause toggle-button and checkbox to line up properly*/ - - display: inline-block; - vertical-align: middle; -} -.onyx-checkbox[checked] { - background-position: 0px -32px; -} -.onyx-checkbox[disabled] { - opacity: 0.4; -} -/* Grabber.css */ -.onyx-grabber { - background: url(./../images/grabbutton.png) no-repeat center; - width: 23px; - height: 27px; -} -/* Popup.css */ -.onyx-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c url(./../images/gradient.png) repeat-x 0 bottom; -} -.onyx-popup-decorator { - position: relative; -} -/* Groupbox.css */ -.onyx-groupbox > * { - display: block; - /*box-shadow: inset 0px 1px 1px rgba(255,255,255,0.5);*/ - - border-color: #aaaaaa; - border-style: solid; - border-width: 0 1px 1px 1px; - /*padding: 10px;*/ - - /* reset styles that make 'item' look bad if they happen to be there */ - - border-radius: 0; - margin: 0; - font-size: 16px; -} -.onyx-groupbox > *:first-child { - border-top-color: #aaaaaa; - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > *:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > *:first-child:last-child { - border-radius: 4px; -} -.onyx-groupbox-header { - padding: 2px 10px; - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; - /**/ - - background-color: #4c4c4c; - border: none; - background: #4c4c4c url(./../images/gradient.png) repeat-x 0 10px; -} -.onyx-groupbox .onyx-input-decorator { - display: block; -} -.onyx-groupbox > .onyx-input-decorator { - border-color: #aaaaaa; - border-width: 0 1px 1px 1px; - border-radius: 0; -} -.onyx-groupbox > .onyx-input-decorator:first-child { - border-width: 1px; - border-radius: 4px 4px 0 0; -} -.onyx-groupbox > .onyx-input-decorator:last-child { - border-radius: 0 0 4px 4px; -} -.onyx-groupbox > .onyx-input-decorator:first-child:last-child { - border-radius: 4px; -} -/* Input.css */ -.onyx-input-decorator { - padding: 6px 8px 10px 8px; - border-radius: 3px; - border: 1px solid; - border-color: rgba(0, 0, 0, 0.1); - margin: 0; -} -.onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - border-color: rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-input-decorator.onyx-disabled { - /* FIXME: needed to color a disabled input placeholder. */ - - /*-webkit-text-fill-color: #888;*/ - - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-input-decorator > input { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > input { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > input { - cursor: default; -} -/* Menu.css */ -.onyx-menu, -.onyx.onyx-menu { - min-width: 160px; - top: 100%; - left: 0; - margin-top: 2px; - padding: 3px 0; - border-radius: 3px; -} -.onyx-menu.onyx-menu-up { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 2px; -} -.onyx-toolbar .onyx-menu { - margin-top: 11px; - border-radius: 0 0 3px 3px; -} -.onyx-toolbar .onyx-menu.onyx-menu-up { - margin-top: 0; - margin-bottom: 10px; - border-radius: 3px 3px 0 0; -} -.onyx-menu-item { - display: block; - padding: 10px; -} -.onyx-menu-item:hover { - background: #284152; -} -.onyx-menu-divider, -.onyx-menu-divider:hover { - margin: 6px 0; - padding: 0; - border-bottom: 1px solid #aaa; -} -.onyx-menu-label { - cursor: default; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-menu-label:hover { - background: none; -} -/* customize a toolbar to support menus */ -.onyx-menu-toolbar, -.onyx-toolbar.onyx-menu-toolbar { - position: relative; - z-index: 10; - overflow: visible; -} -/* Picker.css */ -.onyx-picker-decorator .onyx-button { - padding: 10px 18px; -} -.onyx-picker { - top: 0; - margin-top: -3px; - min-width: 0; - width: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; - color: black; - background: #e1e1e1; -} -.onyx-picker.onyx-menu-up { - top: auto; - bottom: 0; - margin-top: 3px; - margin-bottom: -3px; -} -.onyx-picker .onyx-menu-item { - text-align: center; -} -.onyx-picker .onyx-menu-item:hover { - background-color: transparent; -} -.onyx-picker .onyx-menu-item.selected, -.onyx-picker .onyx-menu-item.active, -.onyx-picker .onyx-menu-item:active:hover { - border-top: 1px solid rgba(0, 0, 0, 0.1); - background-color: #cde7fe; - box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.2); -} -.onyx-picker .onyx-menu-item { - border-top: 1px solid rgba(255, 255, 255, 0.5); - border-bottom: 1px solid rgba(0, 0, 0, 0.2); -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:first-child, -.onyx-flyweight-picker :first-child > .onyx-menu-item { - border-top: none; -} -.onyx-picker:not(.onyx-flyweight-picker) .onyx-menu-item:last-child, -.onyx-flyweight-picker :last-child > .onyx-menu-item { - border-bottom: none; -} -/* TextArea.css */ -.onyx-input-decorator > textarea { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - box-shadow: none; - /* Remove scrollbars and resize handle */ - - resize: none; - overflow: auto; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > textarea { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > textarea { - cursor: default; -} -.onyx-textarea { - /* need >=50px for scrollbar to be usable on mac */ - - min-height: 50px; -} -/* RichText.css */ -.onyx-input-decorator > .onyx-richtext { - /* reset */ - - margin: 0; - padding: 0; - border: none; - outline: none; - cursor: pointer; - background-color: transparent; - background-image: none; - font-size: 16px; - min-height: 20px; - min-width: 100px; - box-shadow: none; - /* FIXME: hack for styling reset on Android */ - - /* -webkit-appearance: caret;*/ - -} -.onyx-input-decorator.onyx-focused > .onyx-richtext { - cursor: text; -} -.onyx-input-decorator.onyx-disabled > .onyx-richtext { - cursor: default; -} -/* RadioButton.css */ -.onyx-radiobutton { - padding: 8px 12px; - margin: 0; - outline: 0; - font-size: 16px; - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); - text-align: center; - /**/ - - background: #e7e7e7 url(./../images/gradient.png) repeat-x bottom; - /* IE8 */ - - border: 1px solid #333333; - border: 1px solid rgba(15, 15, 15, 0.2); - /* turn off right-border in a way IE8 ignores, because IE8 does not support :last-child */ - - border-right-color: rgba(0, 0, 0, 0); - box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.2); -} -.onyx-radiobutton:first-child { - border-radius: 3px 0 0 3px; -} -.onyx-radiobutton:last-child { - border-radius: 0px 3px 3px 0px; - /* IE8 */ - - border-right: 1px solid #333333; - border-right: 1px solid rgba(15, 15, 15, 0.2); -} -.onyx-radiobutton.active { - color: #ffffff; - background: #0091f2 url(./../images/gradient-invert.png) repeat-x top; - border-top: 1px solid rgba(15, 15, 15, 0.6); - box-shadow: inset 1px 2px 2px rgba(0, 0, 0, 0.2); -} -/* Scrim.css */ -.onyx-scrim { - z-index: 1; - /* - note: by using pointer-events we allow tapping on scrim - while it is fading out; however, this requires any showing classes - to set pointer events to auto or scrim will not function as expected. - */ - - pointer-events: none; -} -.onyx-scrim.onyx-scrim-translucent { - pointer-events: auto; - background-color: #000000; - opacity: 0.65; - filter: alpha(opacity=65); -} -.onyx-scrim.onyx-scrim-transparent { - pointer-events: auto; - background: transparent; -} -/* TabButton.css */ -.onyx-radiobutton.onyx-tabbutton { - padding: 8px 34px; - font-size: 20px; - border-radius: 0px; -} -/* ToggleButton.css */ -.onyx-toggle-button { - display: inline-block; - height: 32px; - line-height: 32px; - min-width: 64px; - vertical-align: middle; - text-align: center; - /* */ - - border-radius: 3px; - box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.4); - background: #8bba3d url(./../images/gradient-invert.png) repeat-x bottom; - background-size: auto 100%; - /* label */ - - color: #ffffff; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; -} -.onyx-toggle-button.off { - background-color: #b1b1b1 !important; -} -.onyx-toggle-button-knob { - display: inline-block; - width: 30px; - height: 30px; - margin: 1px; - border-radius: 3px; - background: #f6f6f6 url(./../images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-toggle-button .onyx-toggle-button-knob { - box-shadow: -1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: right; -} -.onyx-toggle-button.off .onyx-toggle-button-knob { - box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(0, 0, 0, 0.4); - float: left; -} -.onyx-toggle-button.disabled, -.onyx-icon-button.disabled { - opacity: 0.4; - filter: alpha(opacity=40); -} -.onyx-toggle-content { - min-width: 32px; - padding: 0 6px; -} -.onyx-toggle-content.empty { - padding: 0; -} -.onyx-toggle-content.off { - float: right; -} -.onyx-toggle-content.on { - float: left; -} -/* Toolbar.css */ -.onyx-toolbar { - /* - line-height is unreliable for centering, instead - use vertical-align: middle to align - elements along a common centerline and use - padding to fill out the space. - */ - - padding: 9px 8px 10px 8px; - border: 1px solid #3A3A3A; - background: #4c4c4c url(./../images/gradient.png) repeat-x 0 bottom; - background-size: contain; - color: #ffffff; - /**/ - - white-space: nowrap; - overflow-y: visible; - font-size: 20px; -} -.onyx-toolbar-inline > *, -.enyo-fittable-columns-layout.onyx-toolbar-inline > * { - display: inline-block; - vertical-align: middle; - margin: 4px 6px 5px; - box-sizing: border-box; -} -.onyx-toolbar .onyx-icon-button { - margin: 3px 2px 1px; -} -.onyx-toolbar .onyx-button { - color: #f2f2f2; - background-color: #555656; - border-color: rgba(15, 15, 15, 0.5); - margin-top: 0; - margin-bottom: 0; - height: 50px; -} -.onyx-toolbar .onyx-input-decorator { - margin: 1px 3px; - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.1); - padding: 0px 6px 5px 6px; -} -.onyx-toolbar .onyx-input-decorator.onyx-focused { - box-shadow: inset 0px 1px 4px rgba(0, 0, 0, 0.3); - background-color: #ffffff; -} -.onyx-toolbar .onyx-input-decorator .onyx-input { - color: #e5e5e5; - font-size: 14px; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus { - color: #000000; -} -.onyx-toolbar .onyx-input-decorator .onyx-input:focus::-webkit-input-placeholder { - color: #dddddd; -} -/* Tooltip.css */ -.onyx-tooltip { - z-index: 20; - left: 0; - padding: 4px 6px; - margin-top: 4px; - margin-left: -6px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - color: #ffffff; - background: #216593 url(./../images/gradient.png) repeat-x 0 bottom; - border-radius: 3px; - white-space: nowrap; -} -/*move the tooltip over to the right when displaying the right arrow so it aligns better with the decorator*/ -.onyx-tooltip.right-arrow { - left: 30px; -} -/*prep the left & right arrows using before & after - left arrow uses before & right arrow uses after*/ -.onyx-tooltip::before { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - left: 16px; -} -.onyx-tooltip::after { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - top: -6px; - margin-left: -12px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed below the activator*/ -.onyx-tooltip.below { - top: 100%; -} -.onyx-tooltip.below.right-arrow::after { - border-bottom: 6px solid #1D587F; - top: -6px; -} -.onyx-tooltip.below.left-arrow::before { - border-bottom: 6px solid #1D587F; - top: -6px; -} -/*The following 3 rules handle the left & right arrows when the tooltip is displayed above the activator*/ -.onyx-tooltip.above { - top: -100%; -} -.onyx-tooltip.above.right-arrow::after { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -.onyx-tooltip.above.left-arrow::before { - content: ''; - border-top: 6px solid #1D587F; - top: 100%; -} -/* ProgressBar.css */ -.onyx-progress-bar { - margin: 8px; - height: 8px; - border: 1px solid rgba(15, 15, 15, 0.2); - border-radius: 3px; - background: #b8b8b8 url(./../images/gradient-invert.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar { - height: 100%; - border-radius: 3px; - background: #58abef url(./../images/gradient.png) repeat-x; - background-size: auto 100%; -} -.onyx-progress-bar-bar.striped { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} -.onyx-progress-bar-bar.striped.animated { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -/* ProgressButton.css */ -.onyx-progress-button { - position: relative; - height: 36px; - line-height: 36px; - color: #f1f1f1; - font-size: 16px; - text-overflow: ellipsis; -} -.onyx-progress-button-bar { - height: 36px; -} -.onyx-progress-button-icon { - display: inline-block; - position: absolute; - top: 2px; - right: 0; -} -.onyx-progress-button-client { - display: inline-block; - position: absolute; - top: 0; - left: 0; - right: 36px; - margin-left: 8px; -} -.onyx-progress-button-client > * { - display: inline-block; -} -/* Slider.css */ -.onyx-slider { - position: relative; - margin: 8px 20px; -} -.onyx-slider-taparea { - position: absolute; - top: -11px; - height: 28px; - width: 100%; -} -.onyx-slider-knob { - position: relative; - height: 40px; - width: 40px; - background: url(./../images/slider-handle.png) left top no-repeat; - margin: -23px -20px; -} -.onyx-slider-knob.active, -.onyx-slider-knob.pressed, -.onyx-slider-knob:active:hover { - background-position: 0 -40px; -} -/* RangeSlider.css */ -.onyx-range-slider-knob { - top: -17px; -} -.onyx-range-slider-label { - position: relative; - top: -18px; - text-align: center; - white-space: nowrap; -} -/* Item.css */ -.onyx-item { - padding: 14px; -} -.onyx-highlight, -.onyx-highlight.onyx-swipeable-item-content { - background-color: #dedfdf; -} -.enyo-selected, -.enyo-selected.onyx-swipeable-item-content { - background-color: #c4e3fe; -} -.onyx-item.onyx-swipeable-item { - overflow: hidden; - padding: 0; -} -.onyx-swipeable-item-content { - background-color: #eaeaea; - box-sizing: border-box; - padding: 18px 6px; - min-height: 40px; -} -/* Spinner.css */ -.onyx-spinner { - width: 59px; - height: 58px; - display: inline-block; - background: url(./../images/spinner-dark.gif) no-repeat 0 0; -} -.onyx-spinner.onyx-light { - background: url(./../images/spinner-light.gif) no-repeat 0 0; -} -/* MoreToolbar.css */ -.onyx-more-toolbar { - overflow: visible; - position: relative; - z-index: 10; -} -.onyx-more-toolbar.active { - z-index: 11; -} -.onyx-more-menu { - left: auto; - right: 0px; - min-width: 0; -} -.onyx-more-toolbar .onyx-more-menu > * { - float: right; - clear: both; - margin: 5px; - margin-top: 5px; - margin-bottom: 5px; -} -.onyx-more-button { - background-image: url(./../images/more.png); - width: 32px; - height: 32px; -} -/* DatePicker.css */ -.onyx-datepicker-month { - min-width: 75px; -} -.onyx-datepicker-day { - min-width: 60px; -} -.onyx-datepicker-year { - min-width: 70px; -} -/* TimePicker.css */ -.onyx-timepicker-hour { - min-width: 60px; -} -.onyx-timepicker-minute { - min-width: 60px; -} -.onyx-timepicker-ampm { - min-width: 60px; -} -/* ButtonColors.css */ -.onyx-button.onyx-blue { - background-color: #35A8EE; - color: #F2F2F2; -} -.onyx-button.onyx-affirmative { - background-color: #91BA07; - color: #F2F2F2; -} -.onyx-button.onyx-negative { - background-color: #C51616; - color: #F2F2F2; -} -.onyx-button.onyx-dark { - background-color: #555656; - color: #F2F2F2; -} -.onyx-button.onyx-light { - background-color: #cacaca; - color: #2F2F2F; -} -/* ContextualPopup.css */ -.onyx-contextual-popup-title { - font-weight: bold; - padding: 24px 32px 0px; -} -.onyx-contextual-popup-scroller { - padding: 24px 32px; -} -.onyx-contextual-popup-action-buttons { - display: inline-block; - width: 100%; - text-align: center; -} -.onyx-contextual-popup-action-button { - margin-left: 5px; - margin-right: 5px; -} -.onyx-contextual-popup, -.onyx.onyx-contextual-popup { - font-size: 16px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 8px; - padding: 6px; - color: #ffffff; - background: #4c4c4c; -} -/*setup the nub*/ -.onyx-contextual-popup::after { - content: ''; - position: absolute; - top: -10px; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; -} -/*for popups above activator*/ -.onyx-contextual-popup.vertical.above { - top: auto; - margin-top: -10px; - bottom: 100%; - margin-bottom: 10px; -} -/*for popups below activator*/ -.onyx-contextual-popup.vertical.below { - margin-top: 10px; -} -/*for popups on the left of the activator*/ -.onyx-contextual-popup.right.horizontal { - margin-left: -11px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.left.horizontal { - margin-left: 10px; -} -/*nub positioning*/ -/*horizontally centered nub*/ -.onyx-contextual-popup.vertical::after { - position: absolute; - left: 45%; - border-bottom: 10px solid #4c4c4c; - border-top: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -/*nub near horizontal left*/ -.onyx-contextual-popup.vertical.right::after { - left: 0%; - margin-left: 20px; -} -/*nub near horizontal right*/ -.onyx-contextual-popup.vertical.left::after { - left: 100%; - margin-left: -55px; -} -/*downward facing nub*/ -.onyx-contextual-popup.vertical.above::after { - top: 100%; - border-top: 10px solid #4c4c4c; - border-bottom: none; - border-left: 10px solid transparent; - border-right: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right::after { - top: 0%; - margin-top: -10px; - border-bottom: 10px solid #4c4c4c; - border-left: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.left::after { - top: 0%; - margin-top: -10px; - border-right: 10px solid transparent; -} -/*nub positioning for left/right popups*/ -/*vertically centered nub for popups on left of activator*/ -.onyx-contextual-popup.right::after { - left: 100%; - top: 47%; - margin-right: 20px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on left of activator*/ -.onyx-contextual-popup.right.high::after { - top: 35px; - border-left: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on left of activator*/ -.onyx-contextual-popup.right.low::after { - top: 100%; - margin-top: -55px; - border-left: 10px solid #4C4C4C; -} -/*vertically centered nub for popups on right of activator*/ -.onyx-contextual-popup.left::after { - left: 0%; - margin-left: -20px; - top: 45%; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical top for popups on right of activator*/ -.onyx-contextual-popup.left.high::after { - top: 35px; - border-right: 10px solid #4C4C4C; -} -/*nub near vertical bottom for popups on right of activator*/ -.onyx-contextual-popup.left.low::after { - top: 100%; - margin-top: -55px; - border-right: 10px solid #4C4C4C; -} -/*corners*/ -/*vertical top corners*/ -/*for popups on the left of the activator*/ -.onyx-contextual-popup.vertical.right.corner { - margin-left: 0px; -} -/*for popups on the right of the activator*/ -.onyx-contextual-popup.vertical.left.corner { - margin-left: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.vertical.below.right.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.vertical.below.left.corner::after { - top: 0%; - left: 100%; - margin-top: -10px; - margin-left: -19px; - border-right: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -.onyx-contextual-popup.vertical.below.right.corner::after { - top: 0%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-top: 10px solid transparent; -} -/*vertical bottom corners*/ -.onyx-contextual-popup.left.above.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.right.above.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.vertical.left.above.corner::after { - top: 100%; - margin-left: -19px; - border-right: 10px solid #4C4C4C; - border-bottom: 10px solid transparent; - border-top: none; -} -.onyx-contextual-popup.vertical.right.above.corner::after { - top: 100%; - left: 0%; - margin-left: -1px; - border-left: 10px solid #4c4c4c; - border-bottom: 10px solid transparent; - border-top: none; -} -/*horizontal bottom corners*/ -.onyx-contextual-popup.left.low.corner { - border-bottom-left-radius: 0px; -} -.onyx-contextual-popup.right.low.corner { - border-bottom-right-radius: 0px; -} -.onyx-contextual-popup.left.low.corner::after { - top: 100%; - left: 0%; - margin-top: -19px; - margin-left: -12px; - border-bottom: 10px solid #4c4c4c; - border-right: 10px solid #4c4c4c; -} -.onyx-contextual-popup.right.low.corner::after { - top: 100%; - left: 100%; - margin-top: -19px; - border-bottom: 10px solid#4c4c4c; - border-left: none; -} -/*horizontal top corners*/ -.onyx-contextual-popup.left.high.corner { - border-top-left-radius: 0px; -} -.onyx-contextual-popup.right.high.corner { - border-top-right-radius: 0px; -} -.onyx-contextual-popup.left.high.corner::after { - top: 0%; - left: 0%; - margin-top: -1px; - margin-left: -12px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -.onyx-contextual-popup.right.high.corner::after { - top: 0%; - left: 100%; - margin-top: -1px; - margin-left: -9px; - border-top: 10px solid #4C4C4C; - border-bottom: none; -} -/* some default colors */ -.onyx-dark { - background-color: #555656; -} -.onyx-light { - background-color: #cacaca; -} -.onyx-green { - background-color: #91BA07; -} -.onyx-red { - background-color: #C51616; -} -.onyx-blue { - background-color: #35A8EE; -} diff --git a/lib/onyx/css/onyx.less b/lib/onyx/css/onyx.less deleted file mode 100644 index 63cce3b..0000000 --- a/lib/onyx/css/onyx.less +++ /dev/null @@ -1,5 +0,0 @@ -/* Onyx default parameters defined here */ -@import "onyx-variables.less"; - -/* Onyx rules defined here */ -@import "onyx-rules.less"; diff --git a/lib/onyx/css/package.js b/lib/onyx/css/package.js deleted file mode 100644 index 4cfd706..0000000 --- a/lib/onyx/css/package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "onyx.less" -); diff --git a/lib/onyx/deploy.bat b/lib/onyx/deploy.bat deleted file mode 100644 index 54dfbb1..0000000 --- a/lib/onyx/deploy.bat +++ /dev/null @@ -1,32 +0,0 @@ -@ECHO OFF - -REM make sure we don't stomp variables in calling script -SETLOCAL - -REM the location of this batch file -SET SOURCE="%~dp0" - -REM target location -SET TARGET=%1 - -IF [%TARGET%]==[] GOTO FAIL - -GOTO OK - -:FAIL - -ECHO Must supply target folder parameter, e.g.: -ECHO. -ECHO deploy.bat ../deploy/lib/onyx -ECHO. -GOTO :EOF - -:OK - -REM copy assets -XCOPY %SOURCE%images\*.* %TARGET%\images\ /Q /E - -REM copy root folder files -COPY %SOURCE%*.txt %TARGET%\ >NUL - -ENDLOCAL diff --git a/lib/onyx/deploy.sh b/lib/onyx/deploy.sh deleted file mode 100644 index 068d501..0000000 --- a/lib/onyx/deploy.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -SOURCE=$(cd `dirname $0`; pwd) - -# target location -TARGET=$1 - -if [ x$TARGET = x ]; then - -cat < - - - - controlled inline: onyx toolbar design - - - - - -

    - -

    - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - -
    - - -
    -
    Text in Div
    - -
    -
    -
    - -
    -
    -
    Text in Div
    - -
    -
    -
    - -
    -
    -
    -
    - -
    - - -
    -
    -
    Text in Div
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    Text in Div
    - -
    -
    -
    - -
    -
    -
    -
    - -
    - - -
    -
    -
    Text in Div
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    Text in Div
    - -
    -
    -
    -
    - -
    -
    -
    -
    - - -
    -
    - -
    Text in Div
    - -
    -
    -
    - - -
    -
    -
    -
    - - -
    -
    -
    -
    Text in Div
    - -
    -
    -
    -
    - -
    -
    -
    -
    -
    - - diff --git a/lib/onyx/design/inline.html b/lib/onyx/design/inline.html deleted file mode 100644 index 47b593a..0000000 --- a/lib/onyx/design/inline.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - inline: onyx toolbar design - - - - - -

    -
    - -
    -
    - - -
    Text
    -
    - - -
    -
    Text in Div
    -
    -
    - - -
    - -
    -
    - - -
    -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    -
    - - diff --git a/lib/onyx/design/menu-icon-bookmark.png b/lib/onyx/design/menu-icon-bookmark.png deleted file mode 100644 index 81d23446edba49f7d4a60e0b04dae0ae5ae8718c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1883 zcmV-h2c-CkP)o!!~4C?;@{e`j{)%=!QG{r96-mc^drP}vh6 z&jirKjiM<3DPv)K{~rYM3?JqNiTo}?XNfXIDO|HFh9ZwEa=n!7-@m_w=1k`!npXoM zSH!mv1WHCnNBQED9`n`!h1BCvfr57&@~TKAQcc&i$68#-grp{}3KQR@ac>pkhMakD z_wL=blarHOsZ{FQwzjsHpx>O-($dmIkX|6VLNvs$x~~6l`}XZm>0OBC1hBRz0{mHJ zZ*TACwY9a|=zeZ-ak0`10mCr(oZsYU!C=rw%-a76$|Jd0tgglC1b0>cNT;y$PLBEx)kY_ z{*za*BS(&C1S>m!{J22~xyBg~|5ld*owAZpoRSiifRY_Nc+lwS>3M*~>bknRREcTc zbqY?$rfCYuby9~##EnoVgPbSkSLyy|PA5*B7&&+D+&tzQIe2gc(#0gB6n1ZtMImOP-KTwqO1OeAU8 zN#yY1!>x2Jm1+VWP^v+dc*ftAA==d-GgfzZckkqD%+Aj0xss70Tm&T<|5-)!^2w7Y zcXV`gaLKsBzz}xP9CM8jHeR1z$HKG%%6Rc*qM9 z#BrZnB+FHCLFWlT9>rRwmkr1v(}yA=fP1wF1Pr+5vWh653ZAaM;E4;MJoW9l_WpOz z+H=pwRFxW3P0Dgi>V8c4ytvOk4gq`!%Rywi3S5Iyd7Y6`bPQL0C0(-Sp`IW@F;Bg< zQVJHiA%U@pCYY83 zc0ZUm5N!wr+0Nd#*vI*HLf&)=2!(+}45~;V5hdLYF*L`{{m^qccK#wSNHSU0RsfpY zku@tN6hyN!2Z~9ylXVk7lw2Xey^&}O&D>Ie0GqLBDQbuq)G&uyK-7h%T*7M(_{;Ed zeTAR3ezb+{X$`Ta&n|n%i!zOcPQSx;$U4*S`9deQjiIn=zzj)^rM>0eV}2 zjyASuTeWR`MUUtFtn|$n*bYiJ*;Bu;KA;klRN*SXDotf;Y3I%S;TKoPqLSXs5{7Mv zBY>OhSbL+6HGR^?THC7GD^P2tRADa*#XcBOd8MCK`_)J9u0{&pa12Ff7}wd0leREi zJtYWa<=~;_vH?5tS&t^IbWEdVyNCZ(j$&4ncYZek6sZpMS;ZwO!F(KRt;UX>b*3*D z0*XYr52MJ@&WzHBw8RG+XeH%u0!*WC6p1VDI4|%F#cs@Xz-Ie#-wl@h{+|7x7gI+2 z#wD0V-JixfPNtR{4=qPy`jFU4Lnc-6!T3MK&C~!&2L8*z4pm>yQuTAaKA1 zO~s9e>T;}NIX+C%pZRc{Eq*z|zQGCD25k z$%w0<{M{zjXzS3h*Nr1B>vE5%Ihs;FAxg|=ew0Cevk&tRaLq^aU2~EciVvYn-Xp+iGO^dT(vAoK1xpYpme|bDRp!idO0RR(9 V6nWnJ%Dn&p002ovPDHLkV1n6ngEIgC diff --git a/lib/onyx/design/toolbar-extended.html b/lib/onyx/design/toolbar-extended.html deleted file mode 100644 index c90b47a..0000000 --- a/lib/onyx/design/toolbar-extended.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - onyx toolbar design - - - - -
    - -
    -
    - -
    Text
    -
    - -
    -
    Text in Div
    -
    -
    - -
    - -
    -
    - -
    -
    -
    -
    - -
    - -
    -
    - -
    -
    Text in Div
    -
    -
    - -
    -
    -
    Text in Div
    -
    -
    - -
    -
    -
    -
    Text in Div
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    div
    - -
    -
    -
    -
    -
    div
    - -
    -
    -
    -
    -
    div
    - -
    -
    -
    -
    -
    div
    - -
    -
    -
    -
    -
    div
    - -
    -
    div
    - -
    -
    - -
    - -
    -
    -
    -
    div
    -
    -
    div
    - -
    -
    - -
    - -
    -
    -
    -
    div
    -
    -
    -
    -
    -
    div
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    div
    - -
    -
    div
    - -
    -
    - -
    - -
    -
    - - diff --git a/lib/onyx/design/toolbar.html b/lib/onyx/design/toolbar.html deleted file mode 100644 index 46bddf1..0000000 --- a/lib/onyx/design/toolbar.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - inline: onyx toolbar design - - - - - -

    -
    - -
    -
    - - -
    Text
    -
    - - -
    -
    Text in Div
    -
    -
    - - -
    - -
    -
    - - -
    -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    - - -
    -
    Text in Div
    - -
    -
    -
    -
    - - diff --git a/lib/onyx/images/checkbox.png b/lib/onyx/images/checkbox.png deleted file mode 100644 index 9176591af4192b5f8fc9d1f66f77da078ae4ab5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5462 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 KMNUMnLSTZHmo(J? diff --git a/lib/onyx/images/gradient-invert.png b/lib/onyx/images/gradient-invert.png deleted file mode 100644 index 44ab5ac084b0962fb8d709e84f158ec880744e6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<7!3HE7BzD~bQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F5`$3q|f;CtLC@59p8c`CQpH@h~YuU)o|cQ6aCV1LzC}Pgg&ebxsLQ0EN_9@c;k- diff --git a/lib/onyx/images/gradient.png b/lib/onyx/images/gradient.png deleted file mode 100644 index 58562587c62b21c388f8957ad6e0370dba70487b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 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 diff --git a/lib/onyx/images/search-input-cancel.png b/lib/onyx/images/search-input-cancel.png deleted file mode 100644 index 8056b4a471e0a7da1e438c7d5cc9ef3a9862a813..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{doXXw8qoL zF~q|E?c{^J2NXD5_m;K2ySQ}j!6UXlF-xDC&r)DrS?=4Bc~t#_V$0s79`;Bj?UdzV zf`9U#f3RK_n!RCm*$wtn33t^i9UOLjW(ZBNST85=GK95iYsb&z55cF6Y%VEH4B)F$ z{>}P2g?$%Wa=;Qz<-^~%+VHnAEc;d8GBNA4$633pEE5f`_ypfX~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/lib/onyx/images/slider-handle.png b/lib/onyx/images/slider-handle.png deleted file mode 100644 index 09e12fbd19e1ff9e3faef8f2a2baaffab78688ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3095 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 Pn1F;$An(;T&^-PCGf5vc diff --git a/lib/onyx/package.js b/lib/onyx/package.js deleted file mode 100644 index b55d530..0000000 --- a/lib/onyx/package.js +++ /dev/null @@ -1,4 +0,0 @@ -enyo.depends( - "source", - "css" -); \ No newline at end of file diff --git a/lib/onyx/samples/ButtonGroupSample.html b/lib/onyx/samples/ButtonGroupSample.html deleted file mode 100644 index e6c37a0..0000000 --- a/lib/onyx/samples/ButtonGroupSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Button Group Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ButtonGroupSample.js b/lib/onyx/samples/ButtonGroupSample.js deleted file mode 100644 index edce781..0000000 --- a/lib/onyx/samples/ButtonGroupSample.js +++ /dev/null @@ -1,45 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ButtonGroupSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "RadioGroup"}, - {kind: "onyx.RadioGroup", onActivate:"radioActivated", components: [ - {content: "Alpha", active: true}, - {content: "Beta"}, - {content: "Gamma"} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "TabGroup"}, - {kind: "onyx.RadioGroup", onActivate:"tabActivated", controlClasses: "onyx-tabbutton", components: [ - {content: "Alpha", active: true}, - {content: "Beta"} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Button Group"}, - {kind: "Group", onActivate:"buttonActivated", classes: "onyx-sample-tools group", defaultKind: "onyx.Button", highlander: true, components: [ - {content: "Button A", active: true, classes: "onyx-affirmative"}, - {content: "Button B", classes: "onyx-negative"}, - {content: "Button C", classes: "onyx-blue"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} - ]} - ], - radioActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" radio button is selected."); - } - }, - tabActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" tab button is selected."); - } - }, - buttonActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - this.$.result.setContent("The \"" + inEvent.originator.getContent() + "\" button is selected."); - } - } -}); diff --git a/lib/onyx/samples/ButtonSample.html b/lib/onyx/samples/ButtonSample.html deleted file mode 100644 index 832a0f4..0000000 --- a/lib/onyx/samples/ButtonSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Button Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ButtonSample.js b/lib/onyx/samples/ButtonSample.js deleted file mode 100644 index a038572..0000000 --- a/lib/onyx/samples/ButtonSample.js +++ /dev/null @@ -1,46 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ButtonSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Buttons"}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.Button", content: "Button", ontap:"buttonTapped"} - ]}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.Button", content: "Affirmative", classes: "onyx-affirmative", ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Negative", classes: "onyx-negative", ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Blue", classes: "onyx-blue", ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Dark", classes: "onyx-dark", ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Custom", style: "background-color: purple; color: #F1F1F1;", ontap:"buttonTapped"} - ]}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.Button", content: "Active", classes: "active", ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Disabled", disabled: true, ontap:"buttonTapped"}, - {kind:"onyx.Button", content: "Active Disabled", classes: "active", disabled: true, ontap:"buttonTapped"} - ]}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.Button", content: "Tall Button", style: "height: 70px;", ontap:"buttonTapped"} - ]}, - {classes: "onyx-sample-divider", content: "Buttons with images"}, - {classes: "onyx-sample-tools", components: [ - {kind: "onyx.Button", name:"Image Button", ontap:"buttonTapped", components: [ - {tag: "img", attributes: {src: "assets/favicon.ico"}}, - {content: "There is an image here"} - ]}, - {kind: "onyx.Button", name:"Fishbowl Button", ontap:"buttonTapped", components: [ - {kind: "onyx.Icon", src: "assets/fish_bowl.png"} - ]} - ]}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} - ]} - ], - buttonTapped: function(inSender, inEvent) { - if (inSender.content){ - this.$.result.setContent("The \"" + inSender.getContent() + "\" button was tapped"); - } else { - this.$.result.setContent("The \"" + inSender.getName() + "\" button was tapped"); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/CheckboxSample.html b/lib/onyx/samples/CheckboxSample.html deleted file mode 100644 index 4f0e655..0000000 --- a/lib/onyx/samples/CheckboxSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Checkbox Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/CheckboxSample.js b/lib/onyx/samples/CheckboxSample.js deleted file mode 100644 index d2487e7..0000000 --- a/lib/onyx/samples/CheckboxSample.js +++ /dev/null @@ -1,34 +0,0 @@ -enyo.kind({ - name: "onyx.sample.CheckboxSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Checkboxes"}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.Checkbox", onchange:"checkboxChanged"}, - {kind:"onyx.Checkbox", onchange:"checkboxChanged"}, - {kind:"onyx.Checkbox", onchange:"checkboxChanged", checked: true} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Checkboxes Group"}, - {kind: "Group", classes: "onyx-sample-tools group", onActivate:"groupActivated", highlander: true, components: [ - {kind:"onyx.Checkbox", checked: true}, - {kind:"onyx.Checkbox"}, - {kind:"onyx.Checkbox"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} - ]} - ], - checkboxChanged: function(inSender, inEvent) { - this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); - }, - ordinals: ["1st", "2nd", "3rd"], - groupActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - var selected = inEvent.originator.indexInContainer(); - this.$.result.setContent("The " + this.ordinals[selected] + " checkbox in the group is selected."); - } - } -}); diff --git a/lib/onyx/samples/ContextualPopupSample.html b/lib/onyx/samples/ContextualPopupSample.html deleted file mode 100644 index 7bb8b0e..0000000 --- a/lib/onyx/samples/ContextualPopupSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - Contextual Popup Sample - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ContextualPopupSample.js b/lib/onyx/samples/ContextualPopupSample.js deleted file mode 100644 index fd6131e..0000000 --- a/lib/onyx/samples/ContextualPopupSample.js +++ /dev/null @@ -1,240 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ContextualPopupSample", - kind: "FittableRows", - classes: "onyx enyo-fit", - handlers: { - ontap: "tapHandler" - }, - components: [ - {kind: "onyx.Toolbar", name:"topToolbar", classes: "onyx-menu-toolbar", style:"background-color:lightgray", components: [ - {kind:"FittableColumns", style:"width:100%;", components:[ - {kind: "onyx.MenuDecorator", components: [ - {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ContextualPopup", - title:"Toolbar Button", - floating:true, - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"test2"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"} - ] - } - ]}, - {kind: "onyx.MenuDecorator", fit:true, style:"position:absolute;right:0;", components: [ - {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ContextualPopup", - title:"Toolbar Button", - floating:true, - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"test2"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"}, - {content:"testing 3"}, - {content:"testing 4"}, - {content:"testing 5"}, - {content:"testing 6"} - ] - } - ]} - ]} - ]}, - {kind: "Scroller", fit: true, thumb:false, components:[ - {name:"buttonContainer", kind:"FittableRows", classes:"onyx-contextualpopup-button-container enyo-fit", components:[ - //Top row of buttons - {components:[ - {kind: "onyx.MenuDecorator", style:"display:inline-block", components: [ - {content: "Average"}, - {kind: "onyx.ContextualPopup", - title:"Average", - floating:true, - actionButtons:[ - {content:"Press Me"} - ], - components: [ - {content:"Item 1"}, - {content:"Item 2"}, - {content:"Item 3"}, - {content:"Item 4"}, - {content:"Item 5"} - ] - } - ]}, - - {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ - {content:"Small"}, - {kind: "onyx.ContextualPopup", - title:"Small", - floating:true - } - ]} - ]}, - //Center row of buttons - {fit:true, style:"padding-top:15%;padding-bottom:15%;", components:[ - {kind: "onyx.MenuDecorator", style:"display:inline-block;", components: [ - {content: "Wide"}, - {kind: "onyx.ContextualPopup", - style:"width:300px", - floating:true, - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"test2"} - ], - components: [ - {kind: "Scroller", style:"min-width:150px;", horizontal:"auto", touch:true, thumb:false, components:[ - {content:"testing 1"}, - {content:"testing 2"} - ]} - ] - } - ]}, - {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ - {content:"Long"}, - {kind: "onyx.ContextualPopup", - maxHeight: "200", - title:"Long", - floating:true, - actionButtons:[ - {content:"Press Me"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"}, - {content:"testing 3"}, - {content:"testing 4"}, - {content:"testing 5"}, - {content:"testing 6"}, - {content:"testing 7"}, - {content:"testing 9"}, - {content:"testing 10"}, - {content:"testing 11"}, - {content:"testing 12"}, - {content:"testing 13"}, - {content:"testing 14"}, - {content:"testing 15"}, - {content:"testing 16"}, - {content:"testing 17"}, - {content:"testing 18"}, - {content:"testing 19"}, - {content:"testing 20"}, - {content:"testing 21"}, - {content:"testing 22"}, - {content:"testing 23"}, - {content:"testing 24"}, - {content:"testing 25"}, - {content:"testing 26"}, - {content:"testing 27"}, - {content:"testing 28"}, - {content:"testing 29"}, - {content:"testing 30"} - ] - } - ]} - ]}, - //Bottom row of buttons - {components:[ - {kind: "onyx.MenuDecorator", style:"display:inline-block;", components: [ - {content: "Press Me"}, - {kind: "onyx.ContextualPopup", - title:"Press Me", - floating:true, - style:"width:200px", - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"test2"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"}, - {content:"testing 3"}, - {content:"testing 4"}, - {content:"testing 5"}, - {content:"testing 6"}, - {content:"testing 7"}, - {content:"testing 9"}, - {content:"testing 10"} - ] - } - ]}, - {kind: "onyx.MenuDecorator", style:"display:inline-block;float:right", components: [ - {content:"Try Me"}, - {kind: "onyx.ContextualPopup", - style:"width:250px", - title:"Try Me", - floating:true, - actionButtons:[ - {content:"Do Nothing", classes: "onyx-button-warning"}, - {content:"Dismiss", name:"dismiss_button"} - ], - components: [ - {content:"Item 1"}, - {content:"Item 2"}, - {content:"Item 3"}, - {content:"Item 4"}, - {content:"Item 5"} - ] - } - ]} - ]} - ]} - ]}, - {kind: "onyx.Toolbar", name:"bottomToolbar", classes: "onyx-menu-toolbar", style:"background-color:lightgray", components: [ - {kind:"FittableColumns", style:"width:100%;", components:[ - {kind: "onyx.MenuDecorator", components: [ - {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ContextualPopup", - title:"Toolbar Button", - floating:true, - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"test2"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"}, - {content:"testing 3"}, - {content:"testing 4"}, - {content:"testing 5"}, - {content:"testing 6"} - ] - } - ]}, - {kind: "onyx.MenuDecorator", fit:true, style:"position:absolute;right:0;", components: [ - {kind:onyx.IconButton, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ContextualPopup", name:"facebook", - title:"Toolbar Button", - floating:true, - actionButtons:[ - {content:"test1", classes: "onyx-button-warning"}, - {content:"Dismiss", name:"dismiss_button"} - ], - components: [ - {content:"testing 1"}, - {content:"testing 2"}, - {content:"testing 3"}, - {content:"testing 4"}, - {content:"testing 5"}, - {content:"testing 6"} - ] - } - ]} - ]} - ]} - ], - tapHandler: function(inSender, inEvent) { - if (inEvent.actionButton) { - enyo.log(inEvent.popup); //info about popup it's coming from - enyo.log("action button index: " + inEvent.originator.index); //index of action button - enyo.log("action button name: " + inEvent.originator.name); //name of action button (you can set this - see example use below) - - if (inEvent.originator.name == "dismiss_button"){ - inEvent.popup.hide(); - } - } - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/DatePickerSample.html b/lib/onyx/samples/DatePickerSample.html deleted file mode 100644 index 012f13f..0000000 --- a/lib/onyx/samples/DatePickerSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - DatePicker Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/DatePickerSample.js b/lib/onyx/samples/DatePickerSample.js deleted file mode 100644 index a5e0bfe..0000000 --- a/lib/onyx/samples/DatePickerSample.js +++ /dev/null @@ -1,108 +0,0 @@ -enyo.kind({ - name: "onyx.sample.DatePickerSample", - kind: "FittableRows", - classes: "onyx", - handlers: { - onSelect: "updateDateValues" - }, - components: [ - {kind: "onyx.Toolbar", content:$L("Dates")}, - {kind: "FittableColumns", style: "padding: 10px", components:[ - {components: [ - {content:$L("Choose Locale:"), classes:"onyx-sample-divider"}, - {kind: "onyx.PickerDecorator", style:"padding:10px;", onSelect: "pickerHandler", components: [ - {content: "Pick One...", style: "width: 200px"}, - {kind: "onyx.Picker", components: [ - {content: 'en_us', active:true}, - {content: 'en_ca'}, - {content: 'en_ie'}, - {content: 'en_gb'}, - {content: 'en_mx'}, - {content: 'de_de'}, - {content: 'fr_fr'}, - {content: 'fr_ca'}, - {content: 'it_it'}, - {content: 'es_es'}, - {content: 'es_mx'}, - {content: 'es_us'} - ]} - ]} - ]} - ]}, - {kind:"onyx.Button",content:"Get Dates", style:"margin:10px;", ontap:"getDates"}, - {kind:"onyx.Button",content:"Reset Dates", ontap:"resetDates"}, - {style:"width:100%;height:5px;background-color:black;margin-bottom:5px;"}, - {caption: "Dates", style: "padding: 10px", components: [ - {content:"DATE",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"datePicker1", kind:"onyx.DatePicker"} - ]}, - {kind: "onyx.Groupbox", style:"padding:5px;", components: [ - {kind: "onyx.GroupboxHeader", content: "Value"}, - {name:"datePicker1Value", style:"padding:15px;"} - ]}, - {content:"DATE W/MIN & MAX YEARS",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"datePicker2", kind:"onyx.DatePicker", minYear:2010, maxYear:2020} - ]}, - {kind: "onyx.Groupbox", style:"padding:5px;", components: [ - {kind: "onyx.GroupboxHeader", content: "Value"}, - {name:"datePicker2Value", style:"padding:15px;"} - ]}, - {content:"DATE W/DAYS HIDDEN",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"datePicker3", kind:"onyx.DatePicker", dayHidden:true} - ]}, - {kind: "onyx.Groupbox", style:"padding:5px;", components: [ - {kind: "onyx.GroupboxHeader", content: "Value"}, - {name:"datePicker3Value", style:"padding:15px;"} - ]}, - {content:"DISABLED",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"datePicker4", kind:"onyx.DatePicker", disabled: true} - ]} - ]} - ], - initComponents: function() { - this.inherited(arguments); - this.locale = enyo.g11n.currentLocale().getLocale(); - }, - pickerHandler: function(inSender, inEvent){ - this.locale = inEvent.selected.content; - this.formatDate(); - return true; - }, - formatDate: function(){ - this.$.datePicker1.setLocale(this.locale); - this.$.datePicker2.setLocale(this.locale); - this.$.datePicker3.setLocale(this.locale); - this.$.datePicker4.setLocale(this.locale); - }, - resetDates: function(date) { - var d = new Date(); - this.$.datePicker1.setValue(d); - this.$.datePicker2.setValue(d); - this.$.datePicker3.setValue(d); - this.$.datePicker4.setValue(d); - this.getDates(); - }, - getDates: function(){ - var fmt = this.format(); - this.$.datePicker1Value.setContent(fmt.format(this.$.datePicker1.getValue())); - this.$.datePicker2Value.setContent(fmt.format(this.$.datePicker2.getValue())); - // reformat the formatter to display the Date wiht only Month and year - fmt = this.format('my'); - this.$.datePicker3Value.setContent(fmt.format(this.$.datePicker3.getValue())); - }, - updateDateValues: function(inSender, inEvent){ - var fmt = inEvent.name != "datePicker3" ? this.format() : this.format('my'); - this.$[inEvent.name + "Value"].setContent(fmt.format(inEvent.value)); - }, - format: function(dateComponents) { - return (fmt = new enyo.g11n.DateFmt({ - dateComponents: dateComponents || undefined, - date: 'short', - locale: new enyo.g11n.Locale(this.locale) - })); - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.css b/lib/onyx/samples/DrawerSample.css deleted file mode 100644 index 5d7684c..0000000 --- a/lib/onyx/samples/DrawerSample.css +++ /dev/null @@ -1,33 +0,0 @@ -.drawer-sample { - padding: 10px; -} -.drawer-sample-divider { - color: #F49200; - text-transform: uppercase; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; - font-weight: bold; - margin-bottom: 8px; -} -.drawer-sample-label { - color: #1879CD; - font-size: 18px; - text-transform: uppercase; -} -.drawer-sample-box { - border: 2px solid lightblue; - padding: 4px; - white-space: nowrap; - overflow:hidden; -} -.drawer-sample-mtb { - margin-top: 3px; - margin-bottom: 3px; -} -.drawer-sample-mlr { - margin-left: 6px; - margin-right: 6px; -} -.drawer-sample-o { - border-color: orange; -} \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.html b/lib/onyx/samples/DrawerSample.html deleted file mode 100644 index c713afa..0000000 --- a/lib/onyx/samples/DrawerSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Drawer Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/DrawerSample.js b/lib/onyx/samples/DrawerSample.js deleted file mode 100644 index 299f9fa..0000000 --- a/lib/onyx/samples/DrawerSample.js +++ /dev/null @@ -1,41 +0,0 @@ -enyo.kind({ - name: "onyx.sample.DrawerSample", - classes: "onyx drawer-sample", - components: [ - {content: "Drawers", classes:"drawer-sample-divider"}, - {content: "Activate (V)", classes: "drawer-sample-box drawer-sample-mtb", ontap:"activateDrawer"}, - {name: "drawer", kind: "onyx.Drawer", components: [ - {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"}, - {components: [ - {kind: "onyx.Checkbox", name: "animateSetting", value: true}, - {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"} - ]}, - {content: "Activate (V) (Toggled Animation)", classes: "drawer-sample-box drawer-sample-mtb", ontap:"activateDrawer2"}, - {name: "drawer2", kind: "onyx.Drawer", animated: true, components: [ - {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"} - ]}, - {content: "Vertical Drawer
    Vertical Drawer
    Vertical Drawer
    Vertical Drawer", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"} - ]}, - {content: "Foo
    Foo", allowHtml: true, classes: "drawer-sample-box drawer-sample-mtb"}, - {kind: "FittableColumns", fit: true, ontap: "activateColumnsDrawer", classes: "drawer-sample-box drawer-sample-mtb drawer-sample-o", components: [ - {content: "Activate (H)", classes: "drawer-sample-box drawer-sample-mlr"}, - {name: "columnsDrawer", orient: "h", kind: "onyx.Drawer", open: false, components: [ - {content: "H-Drawer", classes: "drawer-sample-box drawer-sample-mlr"} - ]}, - {content: "Foo", fit: true, classes: "drawer-sample-box drawer-sample-mlr drawer-sample-o"}, - {content: "Foo", classes: "drawer-sample-box drawer-sample-mlr"} - ]}, - {content: "Foo", classes: "drawer-sample-box drawer-sample-mtb"} - ], - activateDrawer: function() { - this.$.drawer.setOpen(!this.$.drawer.open); - }, - activateDrawer2: function() { - this.$.drawer2.setAnimated(this.$.animateSetting.getValue()); - this.$.drawer2.setOpen(!this.$.drawer2.open); - }, - activateColumnsDrawer: function() { - this.$.columnsDrawer.setOpen(!this.$.columnsDrawer.open); - return true; - } -}); diff --git a/lib/onyx/samples/GroupboxSample.html b/lib/onyx/samples/GroupboxSample.html deleted file mode 100644 index 1822ca8..0000000 --- a/lib/onyx/samples/GroupboxSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Groupbox Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/GroupboxSample.js b/lib/onyx/samples/GroupboxSample.js deleted file mode 100644 index b47701d..0000000 --- a/lib/onyx/samples/GroupboxSample.js +++ /dev/null @@ -1,40 +0,0 @@ -enyo.kind({ - name: "onyx.sample.GroupboxSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Groupboxes"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "Header"}, - {content: "I'm a group item!", style: "padding: 8px;"}, - {content: "I'm a group item!", style: "padding: 8px;"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", components: [ - {content: "I'm a group item!", style: "padding: 8px;"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "Header"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", style: "width: 100%", placeholder: "Enter text here"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", style: "width: 100%", value: "Middle"} - ]}, - {kind: "onyx.InputDecorator", style: "background: lightblue;", components: [ - {kind: "onyx.Input", style: "width: 100%;", value: "Last"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", style: "width: 100%", placeholder: "Enter text here"} - ]} - ]}, - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", type: "password", style: "width: 100%", placeholder: "Enter Password"} - ]} - ]} - ] -}); diff --git a/lib/onyx/samples/IconButtonSample.html b/lib/onyx/samples/IconButtonSample.html deleted file mode 100644 index 6c481ff..0000000 --- a/lib/onyx/samples/IconButtonSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - IconButton Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/IconButtonSample.js b/lib/onyx/samples/IconButtonSample.js deleted file mode 100644 index aa0c0c4..0000000 --- a/lib/onyx/samples/IconButtonSample.js +++ /dev/null @@ -1,61 +0,0 @@ -enyo.kind({ - name: "onyx.sample.IconButtonSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Icon"}, - {kind: "onyx.Icon", src: "assets/menu-icon-bookmark.png" }, - {tag: "br"}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Icon Button"}, - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png", disabled: true, ontap:"iconTapped"}, - {tag: "br"}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Grouped Icon Buttons"}, - {kind: "Group", onActivate:"iconGroupActivated", components: [ - {kind: "onyx.IconButton", active: true, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Toggle Icon Buttons"}, - {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", value: true, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", disabled: true, src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.ToggleIconButton", onChange: "toggleChanged", value: true, disabled: true, src: "assets/menu-icon-bookmark.png"}, - {tag: "br"}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Icon Buttons in Toolbar"}, - {kind: "onyx.Toolbar", defaultKind: "onyx.IconButton", components: [ - {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, - {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, - {src: "assets/menu-icon-bookmark.png", ontap:"iconTapped"}, - {kind: "Control"}, - {kind: "Group", tag: null, onActivate:"iconGroupActivated", defaultKind: "onyx.IconButton", components: [ - {src: "assets/menu-icon-bookmark.png", active: true}, - {src: "assets/menu-icon-bookmark.png"}, - {src: "assets/menu-icon-bookmark.png"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} - ]} - ], - iconTappedCounts: {}, - iconTapped: function(inSender, inEvent) { - this.iconTappedCounts[inSender.name] = this.iconTappedCounts[inSender.name] || 0; - this.$.result.setContent("The icon button was tapped: " + (++this.iconTappedCounts[inSender.name])); - }, - toggleChanged: function(inSender, inEvent) { - this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); - }, - ordinals: ["1st", "2nd", "3rd"], - iconGroupActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - var selected = inEvent.originator.indexInContainer(); - this.$.result.setContent("The " + this.ordinals[selected] + " icon button in the group is selected."); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/InputSample.html b/lib/onyx/samples/InputSample.html deleted file mode 100644 index 5ee6303..0000000 --- a/lib/onyx/samples/InputSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Input Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/InputSample.js b/lib/onyx/samples/InputSample.js deleted file mode 100644 index 21842bb..0000000 --- a/lib/onyx/samples/InputSample.js +++ /dev/null @@ -1,68 +0,0 @@ -enyo.kind({ - name: "onyx.sample.InputSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Inputs"}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Enter text here", onchange:"inputChanged"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Search term", onchange:"inputChanged"}, - {kind: "Image", src: "assets/search-input-search.png"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", type:"password", placeholder: "Enter password", onchange:"inputChanged"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {content: "alwaysLookFocused:"}, - {kind: "onyx.Checkbox", onchange: "changeFocus"} - ]} - ]}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", disabled: true, value: "Disabled input"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {content: "Left:"}, - {kind: "onyx.Input", value: "Input Area", onchange:"inputChanged"}, - {content: " :Right"} - ]} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "RichTexts"}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.RichText", style: "width: 200px;", placeholder: "Enter text here", onchange:"inputChanged"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.RichText", style: "width: 200px;", placeholder: "Search term", onchange:"inputChanged"}, - {kind: "Image", src: "assets/search-input-search.png"} - ]} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "TextAreas"}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.TextArea", placeholder: "Enter text here", onchange:"inputChanged"} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.TextArea", placeholder: "Search term", onchange:"inputChanged"}, - {kind: "Image", src: "assets/search-input-search.png"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No input entered yet."} - ]} - ], - inputChanged: function(inSender, inEvent) { - this.$.result.setContent("Input: " + inSender.getValue()); - }, - changeFocus: function(inSender, inEvent) { - this.$.inputDecorator.setAlwaysLooksFocused(inSender.getValue()); - this.$.inputDecorator2.setAlwaysLooksFocused(inSender.getValue()); - this.$.inputDecorator3.setAlwaysLooksFocused(inSender.getValue()); - } -}); diff --git a/lib/onyx/samples/MenuSample.html b/lib/onyx/samples/MenuSample.html deleted file mode 100644 index ebd80af..0000000 --- a/lib/onyx/samples/MenuSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Menu Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/MenuSample.js b/lib/onyx/samples/MenuSample.js deleted file mode 100644 index 0d71c8a..0000000 --- a/lib/onyx/samples/MenuSample.js +++ /dev/null @@ -1,99 +0,0 @@ -enyo.kind({ - name: "onyx.sample.MenuSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Menus in Toolbars"}, - {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ - {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]}, - {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ - {content: "Bookmarks menu"}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Menus from Buttons"}, - {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ - {content: "Popup menu (floating)"}, - {kind: "onyx.Menu", floating: true, components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "3"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ - {content: "Scrolling Popup menu"}, - {kind: "onyx.Menu", components: [ - {name: "menuScroller", kind: "enyo.Scroller", defaultKind: "onyx.MenuItem", vertical: "auto", classes: "enyo-unselectable", maxHeight: "200px", strategyKind: "TouchScrollStrategy", components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "3"}, - {content: "4"}, - {content: "5"}, - {classes: "onyx-menu-divider"}, - {content: "6"}, - {content: "7"} - ]} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [ - {content: "Split Popup menu", kind: "onyx.Button", onActivate: "preventMenuActivate", style: "border-radius: 3px 0 0 3px;"}, - {content: "v", allowHtml:true, style: "border-radius: 0 3px 3px 0;"}, - {kind: "onyx.Menu", components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "3"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"menuSelection", classes:"onyx-sample-result", content:"No menu selection yet."} - ]} - ], - create: function() { - this.inherited(arguments); - }, - showPopup: function(inSender) { - var p = this.$[inSender.popup]; - if (p) { - p.show(); - } - }, - preventMenuActivate: function() { - return true; - }, - itemSelected: function(inSender, inEvent) { - //Menu items send an onSelect event with a reference to themselves & any directly displayed content - if (inEvent.originator.content){ - this.$.menuSelection.setContent(inEvent.originator.content + " Selected"); - } else if (inEvent.selected){ - // Since some of the menu items do not have directly displayed content (they are kinds with subcomponents), - // we have to handle those items differently here. - this.$.menuSelection.setContent(inEvent.selected.controlAtIndex(1).content + " Selected"); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/MoreToolbarSample.html b/lib/onyx/samples/MoreToolbarSample.html deleted file mode 100644 index 96e1730..0000000 --- a/lib/onyx/samples/MoreToolbarSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - MoreToolbar Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/MoreToolbarSample.js b/lib/onyx/samples/MoreToolbarSample.js deleted file mode 100644 index 14b1470..0000000 --- a/lib/onyx/samples/MoreToolbarSample.js +++ /dev/null @@ -1,35 +0,0 @@ -enyo.kind({ - name: "onyx.sample.MoreToolbarSample", - classes: "onyx onyx-sample", - kind: "FittableRows", - fit: true, - components: [ - {kind: "onyx.MoreToolbar", components: [ - {content: "More Toolbar", unmoveable: true}, - {kind: "onyx.Button", content: "Alpha"}, - {kind: "onyx.Button", content: "Beta"}, - {kind: "onyx.Button", content: "Gamma", unmoveable: true}, - {kind: "onyx.Button", content: "Epsilon"}, - {kind: "onyx.Button", content: "Othercon"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "pulez"} - ]}, - {kind: "onyx.Button", content: "Maxizon"} - ]}, - {fit: true, style: "background: lightpurple;padding:25px;", components: [ - {content: "The \"More Toolbar\" label and the Gamma button have the unmoveable property set to true."} - ]}, - {kind: "onyx.MoreToolbar", components: [ - {content: "More Toolbar", unmoveable: true}, - {kind: "onyx.Button", content: "Alpha"}, - {kind: "onyx.Button", content: "Beta"}, - {kind: "onyx.Button", content: "Gamma", unmoveable: true}, - {kind: "onyx.Button", content: "Epsilon"}, - {kind: "onyx.Button", content: "Othercon"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "pulez"} - ]}, - {kind: "onyx.Button", content: "Maxizon"} - ]} - ] -}); \ No newline at end of file diff --git a/lib/onyx/samples/PickerSample.html b/lib/onyx/samples/PickerSample.html deleted file mode 100644 index 7ca676f..0000000 --- a/lib/onyx/samples/PickerSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Picker Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/PickerSample.js b/lib/onyx/samples/PickerSample.js deleted file mode 100644 index f9c4086..0000000 --- a/lib/onyx/samples/PickerSample.js +++ /dev/null @@ -1,101 +0,0 @@ -enyo.kind({ - name: "onyx.sample.PickerSample", - kind: "FittableRows", - classes: "onyx onyx-sample", - handlers: { - onSelect: "itemSelected" - }, - components: [ - {content: "Default Picker", classes:"onyx-sample-divider"}, - {kind: "onyx.PickerDecorator", components: [ - {}, - {kind: "onyx.Picker", components: [ - {content: "Gmail", active: true}, - {content: "Yahoo"}, - {content: "Outlook"}, - {content: "Hotmail"} - ]} - ]}, - {tag: "br"}, - {content: "Picker with Static Button", classes:"onyx-sample-divider"}, - {kind: "onyx.PickerDecorator", components: [ - {kind: "onyx.PickerButton", content: "Pick One...", style: "width: 200px"}, - {kind: "onyx.Picker", components: [ - {content: "Hello!"}, - {content: "I am busy."}, - {content: "Good Bye."} - ]} - ]}, - {tag: "br"}, - {content: "Integer Picker", classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.PickerDecorator", components: [ - {style: "min-width: 60px;"}, - {kind: "onyx.IntegerPicker", min: 0, max: 25, value: 5} - ]} - ]}, - {tag: "br"}, - {content: "Other Pickers", classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {content: "Date", classes: "onyx-sample-label"}, - {kind: "onyx.PickerDecorator", components: [ - {}, - {name: "monthPicker", kind: "onyx.Picker"} - ]}, - {kind: "onyx.PickerDecorator", components: [ - {style: "min-width: 60px;"}, - {name: "dayPicker", kind: "onyx.Picker"} - ]}, - {classes: "onyx-toolbar-inline", style:"margin: 0px;", components: [ - {content: "Year", classes: "onyx-sample-label"}, - {kind: "onyx.PickerDecorator", components: [ - {name:"yearPickerButton", style: "min-width: 80px;"}, - {name: "yearPicker", kind: "onyx.FlyweightPicker", count: 200, onSetupItem: "setupYear", components: [ - {name: "year"} - ]} - ]} - ]} - ]}, - {tag: "br"}, - {classes: "onyx-toolbar-inline", components: [ - {kind: "onyx.PickerDecorator", components: [ - {}, - {kind: "onyx.Picker", components: [ - {content: "Gmail"}, - {content: "Yahoo"}, - {content: "Outlook"}, - {content: "Hotmail", active: true} - ]} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Selection"}, - {name:"pickerSelection", classes:"onyx-sample-result", content: "Nothing picked yet."} - ]} - ], - create: function() { - this.inherited(arguments); - // month - var months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]; - var d = new Date(); - var i, m; - for (i=0; (m=months[i]); i++) { - this.$.monthPicker.createComponent({content: m, active: i==d.getMonth()}); - } - // day - for (i=0; i<30; i++) { - this.$.dayPicker.createComponent({content: i+1, active: i==d.getDate()-1}); - } - // year - var y = d.getYear(); - this.$.yearPicker.setSelected(y); - this.$.yearPickerButton.setContent(1900+y); - }, - setupYear: function(inSender, inEvent) { - this.$.year.setContent(1900+inEvent.index); - }, - itemSelected: function(inSender, inEvent) { - this.$.pickerSelection.setContent(inEvent.selected.content); - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/PopupSample.html b/lib/onyx/samples/PopupSample.html deleted file mode 100644 index 0135421..0000000 --- a/lib/onyx/samples/PopupSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Popup Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/PopupSample.js b/lib/onyx/samples/PopupSample.js deleted file mode 100644 index 0c5d8e4..0000000 --- a/lib/onyx/samples/PopupSample.js +++ /dev/null @@ -1,65 +0,0 @@ -enyo.kind({ - name: "onyx.sample.PopupSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Popups"}, - {classes: "onyx-sample-tools", components: [ - {kind: "onyx.Button", content: "Basic Popup", ontap: "showPopup", popup: "basicPopup"}, - {name: "basicPopup", kind: "onyx.Popup", centered: true, floating: true, classes:"onyx-sample-popup", style: "padding: 10px;", content: "Popup..."}, - {tag: "br"}, - {kind: "onyx.Button", content: "Popup w/Spinner (Dark)", ontap: "showPopup", popup: "spinnerPopup"}, - {name: "spinnerPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", centered: true, floating: true, onHide: "popupHidden", scrim: true, components: [ - {kind: "onyx.Spinner"}, - {content: "Popup"} - ]}, - {tag: "br"}, - {kind: "onyx.Button", content: "Popup w/Spinner (Light)", ontap: "showPopup", popup: "lightPopup"}, - {name: "lightPopup", classes: "onyx-sample-popup", style: "background: #eee;color: black;", kind: "onyx.Popup", centered: true, floating: true, onHide: "popupHidden", scrim: true, components: [ - {kind: "onyx.Spinner", classes: "onyx-light"}, - {content: "Popup"} - ]}, - {tag: "br"}, - {kind: "onyx.Button", content: "Modal Popup with Input", ontap: "showPopup", popup: "modalPopup"}, - {name: "modalPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input"} - ]}, - {tag: "br"}, - {kind: "onyx.Button", content: "Close", ontap: "closeModalPopup"}, - {kind: "onyx.Button", content: "Another!", ontap: "showPopup", popup: "lightPopup"} - ]}, - {tag: "br"}, - {kind: "onyx.Button", content: "Popup at Event (right)", ontap: "showPopupAtEvent", popup: "rightEventPopup", style: "float: right;"}, - {kind: "onyx.Button", content: "Popup at Event", ontap: "showPopupAtEvent", popup: "leftEventPopup"}, - {name: "leftEventPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", modal: true, floating: true, content: "Anchor defaults
    to top left corner", allowHtml: true}, - {name: "rightEventPopup", classes: "onyx-sample-popup", kind: "onyx.Popup", modal: true, floating: true, content: "Adjusts anchor to
    stay in viewport", allowHtml: true} - ]} - ], - showPopup: function(inSender) { - var p = this.$[inSender.popup]; - if (p) { - p.show(); - } - }, - showPopupAtEvent: function(inSender, inEvent) { - var p = this.$[inSender.popup]; - if (p) { - p.showAtEvent(inEvent); - } - }, - popupHidden: function() { - // FIXME: needed to hide ios keyboard - document.activeElement.blur(); - if(this.$.modalPopup.showing) { // Refocus input on modal - enyo.job("focus", enyo.bind(this.$.input, "focus"), 500); - } - }, - popupShown: function() { - // FIXME: does not focus input on android. - this.$.input.focus(); - enyo.job("focus", enyo.bind(this.$.input, "focus"), 500); - }, - closeModalPopup: function() { - this.$.modalPopup.hide(); - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/ProgressSample.html b/lib/onyx/samples/ProgressSample.html deleted file mode 100644 index 5c1213f..0000000 --- a/lib/onyx/samples/ProgressSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Progress Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ProgressSample.js b/lib/onyx/samples/ProgressSample.js deleted file mode 100644 index b9d65f8..0000000 --- a/lib/onyx/samples/ProgressSample.js +++ /dev/null @@ -1,81 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ProgressSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Progress Bars"}, - {kind: "onyx.ProgressBar", progress: 25}, - {kind: "onyx.ProgressBar", animateStripes: false, progress: 25}, - {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-green"}, - {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-red"}, - {kind: "onyx.ProgressBar", progress: 25, barClasses: "onyx-dark"}, - {kind: "onyx.ProgressBar", animateStripes: false, barClasses: "onyx-light", progress: 50}, - {kind: "onyx.ProgressBar", showStripes: false, progress: 75}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Progress Buttons"}, - {kind: "onyx.ProgressButton", progress: 25, onCancel:"clearValue", components: [ - {content: "0"}, - {content: "100", style: "float: right;"} - ]}, - {kind: "onyx.ProgressButton", animateStripes: false, barClasses: "onyx-dark", progress: 50, onCancel:"clearValue"}, - {kind: "onyx.ProgressButton", showStripes: false, progress: 75, onCancel:"clearValue"}, - {tag: "br"}, - {kind: "onyx.InputDecorator", style:"margin-right:10px;", components: [ - {kind: "onyx.Input", placeholder: "Value", style:"width:50px;"} - ]}, - {kind: "onyx.Button", content:"Set", classes:"onyx-sample-spaced-button", ontap:"changeValue"}, - {kind: "onyx.Button", content:"-", classes:"onyx-sample-spaced-button", ontap:"decValue"}, - {kind: "onyx.Button", content:"+", classes:"onyx-sample-spaced-button", ontap:"incValue"}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Checkbox", name:"animateSetting", checked:true}, - {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"}, - {tag: "br"}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Sliders"}, - {kind: "onyx.Slider", min: 10, max: 50, value: 30}, - {tag: "br"}, - {kind: "onyx.Slider", lockBar: false, progress: 20, value: 75}, - {tag: "br"}, - {name: "progressSlider", kind: "onyx.Slider", lockBar: false, value: 75}, - {kind: "onyx.Button", content: "Toggle Progress", ontap: "toggleProgress"} - ], - changeValue: function(inSender, inEvent) { - for (var i in this.$) { - if (this.$[i].kind == "onyx.ProgressBar" || this.$[i].kind == "onyx.ProgressButton") { - if (this.$.animateSetting.getValue()) { - this.$[i].animateProgressTo(this.$.input.getValue()); - } else { - this.$[i].setProgress(this.$.input.getValue()); - } - } - } - }, - incValue: function() { - this.$.input.setValue(Math.min(parseInt(this.$.input.getValue() || 0, 10) + 10, 100)); - this.changeValue(); - }, - decValue: function() { - this.$.input.setValue(Math.max(parseInt(this.$.input.getValue() || 0, 10) - 10, 0)); - this.changeValue(); - }, - clearValue: function(inSender, inEvent) { - inSender.setProgress(0); - }, - toggleProgress: function() { - this._progressing = !this._progressing; - this.nextProgress(); - }, - nextProgress: function() { - if (this._progressing) { - enyo.requestAnimationFrame(enyo.bind(this, function() { - this.incrementProgress(); - setTimeout(enyo.bind(this, "nextProgress"), 500); - }), this.hasNode()); - } - }, - incrementProgress: function() { - var p = this.$.progressSlider; - var i = p.min + ((p.progress - p.min + 5) % (p.max - p.min + 1)); - p.animateProgressTo(i); - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/SliderSample.html b/lib/onyx/samples/SliderSample.html deleted file mode 100644 index b3c52d0..0000000 --- a/lib/onyx/samples/SliderSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Slider Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/SliderSample.js b/lib/onyx/samples/SliderSample.js deleted file mode 100644 index 1f37d4a..0000000 --- a/lib/onyx/samples/SliderSample.js +++ /dev/null @@ -1,98 +0,0 @@ -enyo.kind({ - name: "onyx.sample.SliderSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Sliders"}, - {kind: "onyx.Slider", value: 50, onChanging:"sliderChanging", onChange:"sliderChanged"}, - {tag: "br"}, - {kind: "onyx.Slider", lockBar: false, value: 50, onChanging:"sliderChanging", onChange:"sliderChanged"}, - - {tag: "br"}, - {kind: "onyx.InputDecorator", style:"margin-right:10px;", components: [ - {kind: "onyx.Input", placeholder: "Value", style:"width:50px;"} - ]}, - {kind: "onyx.Button", content:"Set", classes:"onyx-sample-spaced-button", ontap:"changeValue"}, - {kind: "onyx.Button", content:"-", classes:"onyx-sample-spaced-button", ontap:"decValue"}, - {kind: "onyx.Button", content:"+", classes:"onyx-sample-spaced-button", ontap:"incValue"}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Checkbox", name:"animateSetting", value:true}, - {content:"Animated", classes:"enyo-inline onyx-sample-animate-label"}, - {kind: "onyx.Checkbox", onchange: "sliderIncrementChanged", checked: false}, - {content: "increment by 7", classes:"enyo-inline"}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No slider moved yet."} - ]}, - {tag: "br"}, - {tag: "br"}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "RangeSlider"}, - {tag: "br"}, - {kind: "onyx.RangeSlider", rangeMin: 100, rangeMax: 500, rangeStart: 200, rangeEnd: 400, increment: 20, showLabels: true, onChanging: "rangeSliderChanging", onChange: "rangeSliderChanged"}, - {components: [ - {style: "width:20%; display:inline-block; text-align:left;", content: "$100"}, - {style: "width:60%; display:inline-block; text-align:center;", content: "$300"}, - {style: "width:20%; display:inline-block; text-align:right;", content: "$500"} - ]}, - {tag: "br"}, - {kind: "onyx.Checkbox", onchange: "rangeSliderIncrementChanged", checked: true}, - {content: "increment by 20", classes:"enyo-inline"}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"rangeSliderResult", classes:"onyx-sample-result", content:"RangeSlider not moved yet."} - ]} - ], - changeValue: function(inSender, inEvent) { - for (var i in this.$) { - if (this.$[i].kind == "onyx.Slider") { - if (this.$.animateSetting.getValue()) { - this.$[i].animateTo(this.$.input.getValue()); - } else { - this.$[i].setValue(this.$.input.getValue()); - } - } - } - }, - incValue: function() { - this.$.input.setValue(Math.min(parseInt(this.$.input.getValue() || 0, 10) + 10, 100)); - this.changeValue(); - }, - decValue: function() { - this.$.input.setValue(Math.max(parseInt(this.$.input.getValue() || 0, 10) - 10, 0)); - this.changeValue(); - }, - sliderChanging: function(inSender, inEvent) { - this.$.result.setContent(inSender.name + " changing: " + Math.round(inSender.getValue())); - }, - sliderChanged: function(inSender, inEvent) { - this.$.result.setContent(inSender.name + " changed to " + Math.round(inSender.getValue()) + "."); - }, - rangeSliderIncrementChanged: function(inSender, inEvent) { - this.$.rangeSlider.setIncrement(inSender.getValue() ? 20 : 0); - }, - sliderIncrementChanged: function(inSender, inEvent) { - this.$.slider2.setIncrement(inSender.getValue() ? 7 : 0); - this.$.slider.setIncrement(inSender.getValue() ? 7 : 0); - }, - updateRangeLabels: function(slider) { - slider.setStartLabel("--> " + Math.floor(slider.getRangeStart())); - slider.setEndLabel(Math.floor(slider.getRangeEnd()) + "<--"); - }, - rangeSliderChanging: function(inSender, inEvent) { - this.updateRangeLabels(inSender); - this.$.rangeSliderResult.setContent("Range changing: $" + Math.round(inSender.getRangeStart()) + " - $" + Math.round(inSender.getRangeEnd())); - }, - rangeSliderChanged: function(inSender, inEvent) { - this.updateRangeLabels(inSender); - this.$.rangeSliderResult.setContent("Range changed to $" + Math.round(inSender.getRangeStart()) + " - $" + Math.round(inSender.getRangeEnd()) + "."); - }, - create: function() { - this.inherited(arguments); - this.updateRangeLabels(this.$.rangeSlider); - } -}); diff --git a/lib/onyx/samples/SpinnerSample.html b/lib/onyx/samples/SpinnerSample.html deleted file mode 100644 index c13ed23..0000000 --- a/lib/onyx/samples/SpinnerSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Spinner Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/SpinnerSample.js b/lib/onyx/samples/SpinnerSample.js deleted file mode 100644 index f04cff1..0000000 --- a/lib/onyx/samples/SpinnerSample.js +++ /dev/null @@ -1,18 +0,0 @@ -enyo.kind({ - name: "onyx.sample.SpinnerSample", - classes: "onyx onyx-sample", - handlers: { - onSelect: "itemSelected" - }, - components: [ - {classes: "onyx-sample-divider", content: "Light Spinner"}, - {style:"background:black; border-radius:5px; padding:15px", components: [ - {kind: "onyx.Spinner"} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Dark Spinner"}, - {style:"background:white; border-radius:5px; padding:15px", components: [ - {kind: "onyx.Spinner", classes: "onyx-light"} - ]} - ] -}); diff --git a/lib/onyx/samples/TimePickerSample.html b/lib/onyx/samples/TimePickerSample.html deleted file mode 100644 index dc4de12..0000000 --- a/lib/onyx/samples/TimePickerSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - TimePicker Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/TimePickerSample.js b/lib/onyx/samples/TimePickerSample.js deleted file mode 100644 index 2be02d4..0000000 --- a/lib/onyx/samples/TimePickerSample.js +++ /dev/null @@ -1,100 +0,0 @@ -enyo.kind({ - name: "onyx.sample.TimePickerSample", - kind: "FittableRows", - classes: "onyx enyo-fit", - handlers: { - onSelect: "updateTimeValues" - }, - components: [ - {kind: "onyx.Toolbar", content:$L("Times")}, - {kind: "FittableColumns", style: "padding: 10px", components:[ - {components: [ - {content:$L("Choose Locale:"), classes:"onyx-sample-divider"}, - {kind: "onyx.PickerDecorator", style:"padding:10px;", onSelect: "pickerHandler", components: [ - {content: "Pick One...", style: "width: 200px"}, - {kind: "onyx.Picker", components: [ - {content: 'en_us', active:true}, - {content: 'en_ca'}, - {content: 'en_ie'}, - {content: 'en_gb'}, - {content: 'en_mx'}, - {content: 'de_de'}, - {content: 'fr_fr'}, - {content: 'fr_ca'}, - {content: 'it_it'}, - {content: 'es_es'}, - {content: 'es_mx'}, - {content: 'es_us'} - ]} - ]} - ]} - ]}, - - {kind:"onyx.Button",content:"Get Times", style:"margin:10px;", ontap:"getTimes"}, - {kind:"onyx.Button",content:"Reset Times", ontap:"resetTimes"}, - - {style:"width:100%;height:5px;background-color:black;margin-bottom:5px;"}, - {caption: "Dates", style: "padding: 10px", components: [ - {content:"TIME",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"timePicker1", kind:"onyx.TimePicker"} - ]}, - {kind: "onyx.Groupbox", style:"padding:5px;", components: [ - {kind: "onyx.GroupboxHeader", content: "Value"}, - {name:"timePicker1Value", style:"padding:15px;"} - ]}, - {content:"TIME 24 HOUR MODE",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"timePicker2", kind:"onyx.TimePicker", is24HrMode:true} - ]}, - {kind: "onyx.Groupbox", style:"padding:5px;", components: [ - {kind: "onyx.GroupboxHeader", content: "Localized Value"}, - {name:"timePicker2Value", style:"padding:15px;"} - ]}, - {content:"DISABLED",classes:"onyx-sample-divider"}, - {classes: "onyx-toolbar-inline", components: [ - {name:"timePicker3", kind:"onyx.TimePicker", disabled: true} - ]} - ]} - ], - initComponents: function() { - this.inherited(arguments); - this.locale = enyo.g11n.currentLocale().getLocale(); - }, - pickerHandler: function(inSender, inEvent){ - this.locale = inEvent.selected.content; - this.formatTime(); - return true; - }, - formatTime: function(){ - this.$.timePicker1.setLocale(this.locale); - this.$.timePicker2.setLocale(this.locale); - this.$.timePicker2.setIs24HrMode(true); - this.$.timePicker3.setLocale(this.locale); - }, - resetTimes: function(date) { - var d = new Date(); - this.$.timePicker1.setValue(d); - this.$.timePicker2.setValue(d); - this.$.timePicker3.setValue(d); - - this.getTimes(); - }, - getTimes: function(){ - var fmt = new enyo.g11n.DateFmt({ - time: "short", - locale: new enyo.g11n.Locale(this.locale) - }); - - this.$.timePicker1Value.setContent(fmt.format(this.$.timePicker1.getValue())); - this.$.timePicker2Value.setContent(fmt.format(this.$.timePicker2.getValue())); - }, - updateTimeValues: function(inSender, inEvent){ - var fmt = new enyo.g11n.DateFmt({ - time: "short", - locale: new enyo.g11n.Locale(this.locale) - }); - - this.$[inEvent.name + "Value"].setContent(fmt.format(inEvent.value)); - } -}); \ No newline at end of file diff --git a/lib/onyx/samples/ToggleButtonSample.html b/lib/onyx/samples/ToggleButtonSample.html deleted file mode 100644 index 17ebff7..0000000 --- a/lib/onyx/samples/ToggleButtonSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - ToggleButton Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ToggleButtonSample.js b/lib/onyx/samples/ToggleButtonSample.js deleted file mode 100644 index a0958ea..0000000 --- a/lib/onyx/samples/ToggleButtonSample.js +++ /dev/null @@ -1,35 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ToggleButtonSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "Toggle Buttons"}, - {classes: "onyx-sample-tools", components: [ - {kind:"onyx.ToggleButton", onChange:"toggleChanged", value: true}, - {kind:"onyx.ToggleButton", onChange:"toggleChanged"}, - {kind:"onyx.ToggleButton", onChange:"toggleChanged"}, - {kind:"onyx.ToggleButton", onChange:"toggleChanged", value: true, disabled: true} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Toggle Buttons Group"}, - {kind: "Group", classes: "onyx-sample-tools group", onActivate:"groupActivated", highlander: true, components: [ - {kind:"onyx.ToggleButton"}, - {kind:"onyx.ToggleButton", value: true}, - {kind:"onyx.ToggleButton"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", content: "Result"}, - {name:"result", classes:"onyx-sample-result", content:"No button tapped yet."} - ]} - ], - toggleChanged: function(inSender, inEvent) { - this.$.result.setContent(inSender.name + " was " + (inSender.getValue() ? " selected." : "deselected.")); - }, - ordinals: ["1st", "2nd", "3rd"], - groupActivated: function(inSender, inEvent) { - if (inEvent.originator.getActive()) { - var selected = inEvent.originator.indexInContainer(); - this.$.result.setContent("The " + this.ordinals[selected] + " toggle button in the group is selected."); - } - } -}); diff --git a/lib/onyx/samples/ToolbarSample.html b/lib/onyx/samples/ToolbarSample.html deleted file mode 100644 index 1c435f4..0000000 --- a/lib/onyx/samples/ToolbarSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Toolbar Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/ToolbarSample.js b/lib/onyx/samples/ToolbarSample.js deleted file mode 100644 index 26d5bb5..0000000 --- a/lib/onyx/samples/ToolbarSample.js +++ /dev/null @@ -1,66 +0,0 @@ -enyo.kind({ - name: "onyx.sample.ToolbarSample", - classes: "onyx onyx-sample", - components: [ - {classes: "onyx-sample-divider", content: "ToolBar"}, - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Grabber"}, - {content: "Header"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.Button", content: "Down", classes: "active"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Input"} - ]}, - {kind: "onyx.Button", content: "Right"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Right Input"} - ]}, - {kind: "onyx.Button", content: "More Right"}, - {content: "There's more"}, - {kind: "onyx.Button", content: "Far Right"} - ]}, - {tag: "br"}, - - {classes: "onyx-sample-divider", content: "Scrolling ToolBar"}, - {kind: "Scroller", classes:"onyx-toolbar", touchOverscroll:false, touch:true, vertical:"hidden", style:"margin:0px;", thumb:false, components: [ - {classes: "onyx-toolbar-inline", style: "white-space: nowrap;", components: [ - {kind: "onyx.Grabber"}, - {content: "Header"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.Button", content: "Down", classes: "active"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Input"} - ]}, - {kind: "onyx.Button", content: "Right"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Right Input"} - ]}, - {kind: "onyx.Button", content: "More Right"}, - {content: "There's more"}, - {kind: "onyx.Button", content: "Far Right"} - ]} - ]}, - {tag: "br"}, - - {classes: "onyx-sample-divider", content: "More ToolBar"}, - {kind: "onyx.MoreToolbar", components: [ - {kind: "onyx.Grabber"}, - {content: "Header"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.Button", content: "Down", classes: "active"}, - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Input"} - ]}, - {kind: "onyx.Button", content: "Right"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Right Input"} - ]}, - {kind: "onyx.Button", content: "More Right"}, - {content: "There's more"}, - {kind: "onyx.Button", content: "Far Right"} - ]} - ] -}); diff --git a/lib/onyx/samples/TooltipSample.html b/lib/onyx/samples/TooltipSample.html deleted file mode 100644 index 0c2fc32..0000000 --- a/lib/onyx/samples/TooltipSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Tooltip Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/onyx/samples/TooltipSample.js b/lib/onyx/samples/TooltipSample.js deleted file mode 100644 index 56c5ddf..0000000 --- a/lib/onyx/samples/TooltipSample.js +++ /dev/null @@ -1,92 +0,0 @@ -enyo.kind({ - name: "onyx.sample.TooltipSample", - classes: "onyx onyx-sample", - handlers: { - onSelect: "itemSelected" - }, - components: [ - {classes: "onyx-sample-divider", content: "Tooltips on Toolbar"}, - {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.Button", content: "Tooltip"}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} - ]}, - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", style:"width:130px;", placholder: "Just an input..."} - ]}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [ - {kind: "onyx.MenuDecorator", components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.Tooltip", content: "Bookmarks menu"}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]}, - {kind: "onyx.MenuDecorator", components: [ - {content: "Bookmarks menu"}, - {kind: "onyx.Tooltip", content: "Tap to open..."}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]} - ]}, - {tag: "br"}, - {classes: "onyx-sample-divider", content: "Tooltips on items"}, - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.Button", content: "Tooltip"}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} - ]}, - {tag: "br"}, - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", style:"width:130px;", placholder: "Just an input..."} - ]}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} - ]}, - {tag: "br"}, - {kind: "onyx.MenuDecorator", components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {kind: "onyx.Tooltip", content: "Bookmarks menu"}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]}, - {tag: "br"}, - {kind: "onyx.MenuDecorator", components: [ - {content: "Bookmarks menu"}, - {kind: "onyx.Tooltip", content: "Tap to open..."}, - {kind: "onyx.Menu", components: [ - {components: [ - {kind: "onyx.IconButton", src: "assets/menu-icon-bookmark.png"}, - {content: "Bookmarks"} - ]}, - {content: "Favorites"}, - {classes: "onyx-menu-divider"}, - {content: "Recents"} - ]} - ]} - ] -}); \ No newline at end of file diff --git a/lib/onyx/samples/assets/favicon.ico b/lib/onyx/samples/assets/favicon.ico deleted file mode 100644 index 52c86347fe3e10042c05374362757fa260307d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 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 V6nWnJ%Dn&p002ovPDHLkV1n6ngEIgC diff --git a/lib/onyx/samples/assets/search-input-search.png b/lib/onyx/samples/assets/search-input-search.png deleted file mode 100644 index 36bf1b5161e9d6b22273b681e43c85859c7c8914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstUx|zfk$L9 z0|Vb75M~tB@M-`GN|v}rlmzFem6RtIr7{F0X6BXX`MHKDlo{)p>X~|W{dvH^z-Z&? z;uvD#pPaBjJz{ItR7rv5jDDpYcO(!h6Rp2OW<7aoEG!?f8Q2 zJj<#?unRhbtqqh}2t*&xsK3F-eWYXa` zxggQuD9CVXyFv`_kyj2prvhKJg$bl;%$vd1s=aF==M*Wa?vxjy3einU%nJ`Pb^ZP9 mpyRbM(SW(3%}`mIjUndfKDAF-jSj%TX7F_Nb6Mw<&;$TUqn>~O diff --git a/lib/onyx/samples/package.js b/lib/onyx/samples/package.js deleted file mode 100644 index 1ce23d6..0000000 --- a/lib/onyx/samples/package.js +++ /dev/null @@ -1,23 +0,0 @@ -enyo.depends( - "sample.css", - "DrawerSample.css", - "ButtonGroupSample.js", - "ButtonSample.js", - "CheckboxSample.js", - "GroupboxSample.js", - "IconButtonSample.js", - "InputSample.js", - "PopupSample.js", - "ProgressSample.js", - "SliderSample.js", - "ToggleButtonSample.js", - "ToolbarSample.js", - "DrawerSample.js", - "MenuSample.js", - "TooltipSample.js", - "SpinnerSample.js", - "PickerSample.js", - "DatePickerSample.js", - "TimePickerSample.js", - "ContextualPopupSample.js" -); \ No newline at end of file diff --git a/lib/onyx/samples/sample.css b/lib/onyx/samples/sample.css deleted file mode 100644 index a06cde6..0000000 --- a/lib/onyx/samples/sample.css +++ /dev/null @@ -1,43 +0,0 @@ -.onyx-sample { - padding: 10px; -} -.onyx-sample-tools { - padding-bottom:10px; -} -.onyx-sample-tools > * { - margin: 3px; -} -.onyx-sample-divider { - color: #F49200; - text-transform: uppercase; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; - font-weight: bold; - margin-bottom: 8px; -} -.onyx-sample-result-box { - width:100%; -} -.onyx-sample-result { - padding:8px; -} -.onyx-sample-spaced-button { - margin:3px; -} -.onyx-sample-animate-label { - vertical-align:middle; - padding-left:5px; - margin-right: 15px; -} -.onyx-sample-label { - color: #1879CD; - font-size: 18px; - text-transform: uppercase; -} -.onyx-sample-popup { - font-size: 30px; - text-align: center; -} -.onyx-contextualpopup-button-container{ - padding:10px; -} diff --git a/lib/onyx/source/Button.js b/lib/onyx/source/Button.js deleted file mode 100644 index 8385bc2..0000000 --- a/lib/onyx/source/Button.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - _onyx.Button_ is an enyo.Button with Onyx styling - applied. The color of the button may be customized by specifying a - background color. - - The *onyx-affirmative*, *onyx-negative*, and *onyx-blue* classes provide - some built-in presets. - - {kind: "onyx.Button", content: "Button"}, - {kind: "onyx.Button", content: "Affirmative", classes: "onyx-affirmative"}, - {kind: "onyx.Button", content: "Negative", classes: "onyx-negative"}, - {kind: "onyx.Button", content: "Blue", classes: "onyx-blue"}, - {kind: "onyx.Button", content: "Custom", style: "background-color: purple; color: #F1F1F1;"} - - For more information, see the documentation on - Buttons in the - Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.Button", - kind: "enyo.Button", - classes: "onyx-button enyo-unselectable", - //* @protected - create: function() { - //workaround for FirefoxOS which doesn't support :active:hover css selectors - if(enyo.platform.firefoxOS) { - this.handlers.ondown = "down"; - this.handlers.onleave = "leave"; - } - this.inherited(arguments); - }, - down: function(inSender, inEvent) { - this.addClass("pressed"); - }, - leave: function(inSender, inEvent) { - this.removeClass("pressed"); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/Checkbox.js b/lib/onyx/source/Checkbox.js deleted file mode 100644 index 54155f9..0000000 --- a/lib/onyx/source/Checkbox.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - A box that shows or hides a check mark when clicked. - The onChange event is fired when it is clicked. Use getValue() to fetch - the checked status. - - {kind: "onyx.Checkbox", onchange: "checkboxClicked"} - - checkboxClicked: function(inSender) { - if (inSender.getValue()) { - this.log("I've been checked!"); - } - } -*/ -enyo.kind({ - name: "onyx.Checkbox", - classes: "onyx-checkbox", - //* @protected - kind: enyo.Checkbox, - tag: "div", - handlers: { - // prevent double onchange bubble in IE - onclick: "" - }, - tap: function(inSender, e) { - if (!this.disabled) { - this.setChecked(!this.getChecked()); - this.bubble("onchange"); - } - return !this.disabled; - }, - dragstart: function() { - // Override enyo.Input dragstart handler, to allow drags to propagate for Checkbox - } -}); diff --git a/lib/onyx/source/ContextualPopup.js b/lib/onyx/source/ContextualPopup.js deleted file mode 100644 index a236860..0000000 --- a/lib/onyx/source/ContextualPopup.js +++ /dev/null @@ -1,514 +0,0 @@ -/** - _onyx.ContextualPopup_ is a subkind of enyo.Popup. - Contextual popups serve as child windows that appear near the point of - initiation. Use them for prompting users to select from a defined set of - options; for conducting other quick, single-step interactions in which - context should be maintained; and for presenting simple views, such as - previews. - - A contextual popup is meant to be used in conjunction with a decorator, such - as an onyx.MenuDecorator. The decorator - couples the popup with an activating control, which may be a button or any - other control with an _onActivate_ event. When the control is activated, the - popup shows itself in the correct position relative to the activator. - - Note that, by default, the popup is not floating, so toolbars and controls - with high z-index values may obscure it. You may set the _floating_ property - to true to have the popup always appear on top; however, the popup will not - be in the containing document's flow and so will not scroll with the - document. - - In addition, while contextual popups have their own positioning logic, they - do not currently have their own sizing logic, so be sure to take this into - account when using them. - - {kind: "onyx.MenuDecorator", components: [ - {content: "Show Popup"}, - {kind: "onyx.ContextualPopup", - title: "Sample Popup", - actionButtons: [ - {content:"Button 1", classes: "onyx-button-warning"}, - {content:"Button 2"} - ], - components: [ - {content:"Sample component in popup"} - ] - } - ]} -*/ - -enyo.kind({ - name: "onyx.ContextualPopup", - kind: "enyo.Popup", - modal: true, - autoDismiss: true, - floating:false, - classes: "onyx-contextual-popup enyo-unselectable", - published: { - //* Maximum height of the menu - maxHeight: 100, - //* Toggle scrolling - scrolling: true, - //* Popup title content - title: undefined, - //* Buttons at bottom of popup - actionButtons: [] - }, - - //layout parameters - vertFlushMargin:60, //vertical flush layout margin - horizFlushMargin:50, //horizontal flush layout margin - widePopup:200, //popups wider than this value are considered wide (for layout purposes) - longPopup:200, //popups longer than this value are considered long (for layout purposes) - horizBuffer:16, //do not allow horizontal flush popups past spec'd amount of buffer space on left/right screen edge - - events: { - onTap: "" - }, - handlers: { - onActivate: "itemActivated", - onRequestShowMenu: "requestShow", - onRequestHideMenu: "requestHide" - }, - components: [ - {name:"title", classes:"onyx-contextual-popup-title"}, - {classes:"onyx-contextual-popup-scroller", components:[ - {name:"client", kind: "enyo.Scroller", vertical:"auto", classes:"enyo-unselectable", thumb:false, strategyKind: "TouchScrollStrategy"} - ]}, - {name:"actionButtons", classes:"onyx-contextual-popup-action-buttons"} - ], - scrollerName: "client", - create: function() { - this.inherited(arguments); - this.maxHeightChanged(); - this.titleChanged(); - this.actionButtonsChanged(); - }, - getScroller: function() { - return this.$[this.scrollerName]; - }, - titleChanged: function(){ - this.$.title.setContent(this.title); - }, - actionButtonsChanged: function(){ - for (var i=0;i bottomFlushPt) { - //check/try vertical flush positioning (rule 1.a.i) - if (this.applyVerticalFlushPositioning(leftFlushPt, rightFlushPt)) { - return; - } - - //if vertical doesn't fit then check/try horizontal flush (rule 1.a.ii) - if (this.applyHorizontalFlushPositioning(leftFlushPt, rightFlushPt)) { - return; - } - - //if flush positioning didn't work then try just positioning vertically (rule 1.b.i & rule 1.b.ii) - if (this.applyVerticalPositioning()){ - return; - } - //otherwise check if the activator is in the left or right edges of the view & if so try horizontal positioning - } else if ((this.activatorOffset.left + this.activatorOffset.width) < leftFlushPt || this.activatorOffset.left > rightFlushPt) { - //if flush positioning didn't work then try just positioning horizontally (rule 1.b.iii & rule 1.b.iv) - if (this.applyHorizontalPositioning()){ - return; - } - } - - //Rule 2 - no specific logic below for this rule since it is inheritent to the positioning functions, ie we attempt to never - //position a popup where there isn't enough room for it. - - //Rule 3 - Popup Size based positioning - var clientRect = this.getBoundingRect(this.node); - - //if the popup is wide then use vertical positioning - if (clientRect.width > this.widePopup) { - if (this.applyVerticalPositioning()){ - return; - } - } - //if the popup is long then use horizontal positioning - else if (clientRect.height > this.longPopup) { - if (this.applyHorizontalPositioning()){ - return; - } - } - - //Rule 4 - Favor top or bottom positioning - if (this.applyVerticalPositioning()) { - return; - } - //but if thats not possible try horizontal - else if (this.applyHorizontalPositioning()){ - return; - } - - //Rule 5 - no specific logic below for this rule since it is built into the vertical position functions, ie we attempt to - // use a bottom position for the popup as much possible. - } - }, - //move the popup below or above the activator & verify that it fits on screen - initVerticalPositioning: function() { - this.resetPositioning(); - this.addClass("vertical"); - - var clientRect = this.getBoundingRect(this.node); - var innerHeight = this.getViewHeight(); - - if (this.floating){ - if (this.activatorOffset.top < (innerHeight / 2)) { - this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height, bottom: "auto"}); - this.addClass("below"); - } else { - this.applyPosition({top: this.activatorOffset.top - clientRect.height, bottom: "auto"}); - this.addClass("above"); - } - } else { - //if the popup's bottom goes off the screen then put it on the top of the invoking control - if ((clientRect.top + clientRect.height > innerHeight) && ((innerHeight - clientRect.bottom) < (clientRect.top - clientRect.height))){ - this.addClass("above"); - } else { - this.addClass("below"); - } - } - - //if moving the popup above or below the activator puts it past the edge of the screen then vertical doesn't work - clientRect = this.getBoundingRect(this.node); - if ((clientRect.top + clientRect.height) > innerHeight || clientRect.top < 0){ - return false; - } - - return true; - }, - applyVerticalPositioning: function() { - //if we can't fit the popup above or below the activator then forget vertical positioning - if (!this.initVerticalPositioning()) { - return false; - } - - var clientRect = this.getBoundingRect(this.node); - var innerWidth = this.getViewWidth(); - - if (this.floating){ - //Get the left edge delta to horizontally center the popup - var centeredLeft = this.activatorOffset.left + this.activatorOffset.width/2 - clientRect.width/2; - if (centeredLeft + clientRect.width > innerWidth) {//popup goes off right edge of the screen if centered - this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width - clientRect.width}); - this.addClass("left"); - } else if (centeredLeft < 0) {//popup goes off left edge of the screen if centered - this.applyPosition({left:this.activatorOffset.left}); - this.addClass("right"); - } else {//center the popup - this.applyPosition({left: centeredLeft}); - } - - } else { - //Get the left edge delta to horizontally center the popup - var centeredLeftDelta = this.activatorOffset.left + this.activatorOffset.width/2 - clientRect.left - clientRect.width/2; - if (clientRect.right + centeredLeftDelta > innerWidth) {//popup goes off right edge of the screen if centered - this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width - clientRect.right}); - this.addRemoveClass("left", true); - } else if (clientRect.left + centeredLeftDelta < 0) {//popup goes off left edge of the screen if centered - this.addRemoveClass("right", true); - } else {//center the popup - this.applyPosition({left: centeredLeftDelta}); - } - } - - return true; - }, - applyVerticalFlushPositioning: function(leftFlushPt, rightFlushPt) { - //if we can't fit the popup above or below the activator then forget vertical positioning - if (!this.initVerticalPositioning()) { - return false; - } - - var clientRect = this.getBoundingRect(this.node); - var innerWidth = this.getViewWidth(); - - //If the activator's right side is within our left side cut off use flush positioning - if ((this.activatorOffset.left + this.activatorOffset.width/2) < leftFlushPt){ - //if the activator's left edge is too close or past the screen left edge - if (this.activatorOffset.left + this.activatorOffset.width/2 < this.horizBuffer){ - this.applyPosition({left:this.horizBuffer + (this.floating ? 0 : -clientRect.left)}); - } else { - this.applyPosition({left:this.activatorOffset.width/2 + (this.floating ? this.activatorOffset.left : 0)}); - } - - this.addClass("right"); - this.addClass("corner"); - return true; - } - //If the activator's left side is within our right side cut off use flush positioning - else if (this.activatorOffset.left + this.activatorOffset.width/2 > rightFlushPt) { - if ((this.activatorOffset.left+this.activatorOffset.width/2) > (innerWidth-this.horizBuffer)){ - this.applyPosition({left:innerWidth - this.horizBuffer - clientRect.right}); - } else { - this.applyPosition({left: (this.activatorOffset.left + this.activatorOffset.width/2) - clientRect.right}); - } - this.addClass("left"); - this.addClass("corner"); - return true; - } - - return false; - }, - //move the popup left or right of the activator & verify that it fits on screen - initHorizontalPositioning: function() { - this.resetPositioning(); - - var clientRect = this.getBoundingRect(this.node); - var innerWidth = this.getViewWidth(); - - //adjust horizontal positioning of the popup & nub vertical positioning - if (this.floating){ - if ((this.activatorOffset.left + this.activatorOffset.width) < innerWidth/2) { - this.applyPosition({left: this.activatorOffset.left + this.activatorOffset.width}); - this.addRemoveClass("left", true); - } else { - this.applyPosition({left: this.activatorOffset.left - clientRect.width}); - this.addRemoveClass("right", true); - } - } else { - if (this.activatorOffset.left - clientRect.width > 0) { - this.applyPosition({left: this.activatorOffset.left - clientRect.left - clientRect.width}); - this.addRemoveClass("right", true); - } else { - this.applyPosition({left: this.activatorOffset.width}); - this.addRemoveClass("left", true); - } - } - this.addRemoveClass("horizontal", true); - - //if moving the popup left or right of the activator puts it past the edge of the screen then horizontal won't work - clientRect = this.getBoundingRect(this.node); - if (clientRect.left < 0 || (clientRect.left + clientRect.width) > innerWidth){ - return false; - } - return true; - - }, - applyHorizontalPositioning: function() { - //if we can't fit the popup left or right of the activator then forget horizontal positioning - if (!this.initHorizontalPositioning()) { - return false; - } - - var clientRect = this.getBoundingRect(this.node); - var innerHeight = this.getViewHeight(); - var activatorCenter = this.activatorOffset.top + this.activatorOffset.height/2; - - if (this.floating){ - //if the activator's center is within 10% of the center of the view, vertically center the popup - if ((activatorCenter >= (innerHeight/2 - 0.05 * innerHeight)) && (activatorCenter <= (innerHeight/2 + 0.05 * innerHeight))) { - this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height/2 - clientRect.height/2, bottom: "auto"}); - } else if (this.activatorOffset.top + this.activatorOffset.height < innerHeight/2) { //the activator is in the top 1/2 of the screen - this.applyPosition({top: this.activatorOffset.top - this.activatorOffset.height, bottom: "auto"}); - this.addRemoveClass("high", true); - } else { //otherwise the popup will be positioned in the bottom 1/2 of the screen - this.applyPosition({top: this.activatorOffset.top - clientRect.height + this.activatorOffset.height*2, bottom: "auto"}); - this.addRemoveClass("low", true); - } - } else { - //if the activator's center is within 10% of the center of the view, vertically center the popup - if ((activatorCenter >= (innerHeight/2 - 0.05 * innerHeight)) && (activatorCenter <= (innerHeight/2 + 0.05 * innerHeight))) { - this.applyPosition({top: (this.activatorOffset.height - clientRect.height)/2}); - } else if (this.activatorOffset.top + this.activatorOffset.height < innerHeight/2) { //the activator is in the top 1/2 of the screen - this.applyPosition({top: -this.activatorOffset.height}); - this.addRemoveClass("high", true); - } else { //otherwise the popup will be positioned in the bottom 1/2 of the screen - this.applyPosition({top: clientRect.top - clientRect.height - this.activatorOffset.top + this.activatorOffset.height}); - this.addRemoveClass("low", true); - } - } - return true; - }, - applyHorizontalFlushPositioning: function(leftFlushPt, rightFlushPt) { - //if we can't fit the popup left or right of the activator then forget vertical positioning - if (!this.initHorizontalPositioning()) { - return false; - } - - var clientRect = this.getBoundingRect(this.node); - var innerWidth = this.getViewWidth(); - - //adjust vertical positioning (high or low nub & popup position) - if (this.floating){ - if (this.activatorOffset.top < (innerHeight/2)){ - this.applyPosition({top: this.activatorOffset.top + this.activatorOffset.height/2}); - this.addRemoveClass("high", true); - } else { - this.applyPosition({top:this.activatorOffset.top + this.activatorOffset.height/2 - clientRect.height}); - this.addRemoveClass("low", true); - } - } else { - if (((clientRect.top + clientRect.height) > innerHeight) && ((innerHeight - clientRect.bottom) < (clientRect.top - clientRect.height))) { - this.applyPosition({top: clientRect.top - clientRect.height - this.activatorOffset.top - this.activatorOffset.height/2}); - this.addRemoveClass("low", true); - } else { - this.applyPosition({top: this.activatorOffset.height/2}); - this.addRemoveClass("high", true); - } - } - - //If the activator's right side is within our left side cut off use flush positioning - if ((this.activatorOffset.left + this.activatorOffset.width) < leftFlushPt){ - this.addClass("left"); - this.addClass("corner"); - return true; - } - //If the activator's left side is within our right side cut off use flush positioning - else if (this.activatorOffset.left > rightFlushPt) { - this.addClass("right"); - this.addClass("corner"); - return true; - } - - return false; - }, - getBoundingRect: function(inNode){ - // getBoundingClientRect returns top/left values which are relative to the viewport and not absolute - var o = inNode.getBoundingClientRect(); - if (!o.width || !o.height) { - return { - left: o.left, - right: o.right, - top: o.top, - bottom: o.bottom, - width: o.right - o.left, - height: o.bottom - o.top - }; - } - return o; - }, - getViewHeight: function() { - return (window.innerHeight === undefined) ? document.documentElement.clientHeight : window.innerHeight; - }, - getViewWidth: function() { - return (window.innerWidth === undefined) ? document.documentElement.clientWidth : window.innerWidth; - }, - resetPositioning: function() { - this.removeClass("right"); - this.removeClass("left"); - this.removeClass("high"); - this.removeClass("low"); - this.removeClass("corner"); - this.removeClass("below"); - this.removeClass("above"); - this.removeClass("vertical"); - this.removeClass("horizontal"); - - this.applyPosition({left: "auto"}); - this.applyPosition({top: "auto"}); - }, - resizeHandler: function() { - this.inherited(arguments); - this.adjustPosition(); - }, - requestHide: function(){ - this.setShowing(false); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/DatePicker.js b/lib/onyx/source/DatePicker.js deleted file mode 100644 index 51f32b2..0000000 --- a/lib/onyx/source/DatePicker.js +++ /dev/null @@ -1,205 +0,0 @@ -/** - _onyx.DatePicker_ is a group of onyx.Picker - controls displaying the current date. The user may change the _day_, - _month_, and _year_ values. - - By default, _DatePicker_ tries to determine the current locale and use its - rules to format the date (including the month name). In order to do this - successfully, the _g11n_ library must be loaded; if it is not loaded, the - control defaults to using standard U.S. date format. - - The _day_ field is automatically populated with the proper number of days - for the selected month and year. - */ -enyo.kind({ - name: "onyx.DatePicker", - classes: "onyx-toolbar-inline", - published: { - //* If true, control is shown as disabled, and user can't select new values - disabled: false, - /** - Current locale used for formatting. Can be set after control - creation, in which case the control will be updated to reflect the - new value. - */ - locale: "en_us", - //* If true, the day field is hidden - dayHidden: false, - //* If true, the month field is hidden - monthHidden: false, - //* If true, the year field is hidden - yearHidden: false, - //* Optional minimum year value - minYear: 1900, - //* Optional maximum year value - maxYear: 2099, - /** - The current Date object. When a Date object is passed to _setValue_, - the control is updated to reflect the new value. _getValue_ returns - a Date object. - */ - value: null - }, - events: { - /** - Fires when one of the DatePicker's fields is selected. - - _inEvent.name_ contains the name of the DatePicker that generated - the event. - - _inEvent.value_ contains the current Date value of the control. - */ - onSelect: "" - }, - create: function() { - this.inherited(arguments); - if (enyo.g11n) { - this.locale = enyo.g11n.currentLocale().getLocale(); - } - this.initDefaults(); - }, - initDefaults: function() { - // Fall back to en_us as default - var months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]; - - //Attempt to use the g11n lib (ie assume it is loaded) - if (enyo.g11n) { - this._tf = new enyo.g11n.Fmts({locale:this.locale}); - months = this._tf.getMonthFields(); - } - - this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : 'mdy'); - - this.dayHiddenChanged(); - this.monthHiddenChanged(); - this.yearHiddenChanged(); - - //Fill month, year & day pickers with values - var d = this.value = this.value || new Date(); - for (var i=0,m; (m=months[i]); i++) { - this.$.monthPicker.createComponent({content: m, value:i, active: i==d.getMonth()}); - } - - var y = d.getFullYear(); - this.$.yearPicker.setSelected(y-this.minYear); - - for (i=1; i<=this.monthLength(d.getYear(), d.getMonth()); i++) { - this.$.dayPicker.createComponent({content:i, value:i, active: i==d.getDate()}); - } - }, - monthLength: function(inYear, inMonth) { - // determine number of days in a particular month/year - return 32 - new Date(inYear, inMonth, 32).getDate(); - }, - setupYear: function(inSender, inEvent) { - this.$.year.setContent(this.minYear+inEvent.index); - }, - setupPickers: function(ordering) { - var orderingArr = ordering.split(""); - var o,f,l; - for(f = 0, l = orderingArr.length; f < l; f++) { - o = orderingArr[f]; - switch (o){ - case 'd': this.createDay(); - break; - case 'm': this.createMonth(); - break; - case 'y': this.createYear(); - break; - default: break; - } - } - }, - createYear: function() { - var yearCount = this.maxYear - this.minYear; - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateYear", components: [ - {classes:"onyx-datepicker-year", name: "yearPickerButton", disabled: this.disabled}, - {name: "yearPicker", kind: "onyx.FlyweightPicker", count: ++yearCount, onSetupItem: "setupYear", components: [ - {name: "year"} - ]} - ]} - ); - }, - createMonth: function() { - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateMonth", components: [ - {classes:"onyx-datepicker-month", name: "monthPickerButton", disabled: this.disabled}, - {name: "monthPicker", kind: "onyx.Picker"} - ]} - ); - }, - createDay: function() { - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateDay", components: [ - {classes:"onyx-datepicker-day", name: "dayPickerButton", disabled: this.disabled}, - {name: "dayPicker", kind: "onyx.Picker"} - ]} - ); - }, - localeChanged: function() { - this.refresh(); - }, - dayHiddenChanged: function() { - this.$.dayPicker.getParent().setShowing(this.dayHidden ? false : true); - }, - monthHiddenChanged: function() { - this.$.monthPicker.getParent().setShowing(this.monthHidden ? false : true); - }, - yearHiddenChanged: function() { - this.$.yearPicker.getParent().setShowing(this.yearHidden ? false : true); - }, - minYearChanged: function() { - this.refresh(); - }, - maxYearChanged: function() { - this.refresh(); - }, - valueChanged: function(){ - this.refresh(); - }, - disabledChanged: function() { - this.$.yearPickerButton.setDisabled(this.disabled); - this.$.monthPickerButton.setDisabled(this.disabled); - this.$.dayPickerButton.setDisabled(this.disabled); - }, - updateDay: function(inSender, inEvent){ - var date = this.calcDate(this.value.getFullYear(), - this.value.getMonth(), - inEvent.selected.value); - this.doSelect({name:this.name, value:date}); - this.setValue(date); - return true; - }, - updateMonth: function(inSender, inEvent){ - var date = this.calcDate(this.value.getFullYear(), - inEvent.selected.value, - this.value.getDate()); - this.doSelect({name:this.name, value:date}); - this.setValue(date); - return true; - }, - updateYear: function(inSender, inEvent){ - //if the node wasn't found (issue around FlyWeightRepeater/Picker) don't update the picker - if (inEvent.originator.selected != -1) { - var date = this.calcDate(this.minYear + inEvent.originator.selected, - this.value.getMonth(), - this.value.getDate()); - this.doSelect({name:this.name, value:date}); - this.setValue(date); - } - return true; - }, - calcDate: function(year, month, day){ - return new Date(year,month,day, - this.value.getHours(), - this.value.getMinutes(), - this.value.getSeconds(), - this.value.getMilliseconds()); - }, - refresh: function(){ - this.destroyClientControls(); - this.initDefaults(); - this.render(); - } -}); diff --git a/lib/onyx/source/Drawer.js b/lib/onyx/source/Drawer.js deleted file mode 100644 index da94338..0000000 --- a/lib/onyx/source/Drawer.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - _onyx.Drawer_ is a control that appears or disappears based on its _open_ - property. By default, the drawer appears or disappears with a sliding - animation whose direction is determined by the _orient_ property. - - For more information, see the documentation on - Drawers in the - Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.Drawer", - published: { - //* The visibility state of the drawer's associated control - open: true, - /** - Direction of the opening/closing animation--either "v" for vertical - or "h" for horizontal - */ - orient: "v", - //* If true, the opening/closing transition will be animated. - animated: true - }, - //* @protected - style: "overflow: hidden; position: relative;", - tools: [ - {kind: "Animator", onStep: "animatorStep", onEnd: "animatorEnd"}, - {name: "client", style: "position: relative;", classes: "enyo-border-box"} - ], - create: function() { - this.inherited(arguments); - this.animatedChanged(); - this.openChanged(); - }, - initComponents: function() { - this.createChrome(this.tools); - this.inherited(arguments); - }, - animatedChanged: function() { - if (!this.animated && this.hasNode() && this.$.animator.isAnimating()) { - this.$.animator.stop(); - this.animatorEnd(); - } - }, - openChanged: function() { - this.$.client.show(); - if (this.hasNode()) { - if (this.$.animator.isAnimating()) { - this.$.animator.reverse(); - } else { - var v = this.orient == "v"; - var d = v ? "height" : "width"; - var p = v ? "top" : "left"; - // unfixing the height/width is needed to properly - // measure the scrollHeight/Width DOM property, but - // can cause a momentary flash of content on some browsers - this.applyStyle(d, null); - var s = this.hasNode()[v ? "scrollHeight" : "scrollWidth"]; - if (this.animated) { - this.$.animator.play({ - startValue: this.open ? 0 : s, - endValue: this.open ? s : 0, - dimension: d, - position: p - }); - } else { - // directly run last frame if not animating - this.animatorEnd(); - } - } - } else { - this.$.client.setShowing(this.open); - } - }, - animatorStep: function(inSender) { - // the actual drawer DOM node adjusts its height - if (this.hasNode()) { - var d = inSender.dimension; - this.node.style[d] = this.domStyles[d] = inSender.value + "px"; - } - // while the client inside the drawer adjusts its position to move out of the visible area - var cn = this.$.client.hasNode(); - if (cn) { - var p = inSender.position; - var o = (this.open ? inSender.endValue : inSender.startValue); - cn.style[p] = this.$.client.domStyles[p] = (inSender.value - o) + "px"; - } - if (this.container) { - this.container.resized(); - } - }, - animatorEnd: function() { - if (!this.open) { - this.$.client.hide(); - } - else { - // save changes to this.domCssText --> see ENYO-1561 - this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles); - // at end of open animation, clean limit on height/width - var v = (this.orient == "v"); - var d = v ? "height" : "width"; - var p = v ? "top" : "left"; - var cn = this.$.client.hasNode(); - // clear out changes to container position & node dimension - if (cn) { - cn.style[p] = this.$.client.domStyles[p] = null; - } - if (this.node) { - this.node.style[d] = this.domStyles[d] = null; - } - } - if (this.container) { - this.container.resized(); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/source/FlyweightPicker.js b/lib/onyx/source/FlyweightPicker.js deleted file mode 100644 index bb84986..0000000 --- a/lib/onyx/source/FlyweightPicker.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - _onyx.FlyweightPicker_, a subkind of onyx.Picker, - is a picker that employs the flyweight pattern. It is used to display a - large list of selectable items. As with - enyo.FlyweightRepeater, - the _onSetupItem_ event allows for customization of item rendering. - - To initialize the FlyweightPicker to a particular value, call _setSelected_ - with the index of the item you wish to select, and call _setContent_ with - the item that should be shown in the activator button. - - FlyweightPicker will send an _onSelect_ event with a selected item's - information. This can be received by a client application to determine which - item was selected. - - enyo.kind({ - handlers: { - onSelect: "itemSelected" - }, - components: [ - {kind: "onyx.PickerDecorator", components: [ - {}, - {name: "yearPicker", kind: "onyx.FlyweightPicker", count: 200, - onSetupItem: "setupYear", components: [ - {name: "year"} - ] - } - ]} - ], - create: function() { - var d = new Date(); - var y = d.getYear(); - this.$.yearPicker.setSelected(y); - this.$.year.setContent(1900+y); - }, - setupYear: function(inSender, inEvent) { - this.$.year.setContent(1900+inEvent.index); - }, - itemSelected: function(inSender, inEvent) { - enyo.log("Picker Item Selected: " + inEvent.selected.content); - } - }) - */ -enyo.kind({ - name: "onyx.FlyweightPicker", - kind: "onyx.Picker", - classes: "onyx-flyweight-picker", - published: { - //* How many rows to render - count: 0 - }, - events: { - /** - Fires when a row is being initialized. The _index_ property contains - the row index, while the _flyweight_ property contains the row - control, for decoration. - */ - onSetupItem: "", - /** - Fires when an item is selected. The _content_ property contains the - content of the selected item, while the _selected_ property contains - its row index. - */ - onSelect: "" - }, - //* @protected - handlers: { - onSelect: "itemSelect" - }, - components: [ - {name: "scroller", kind: "enyo.Scroller", strategyKind: "TouchScrollStrategy", components: [ - {name: "flyweight", kind: "FlyweightRepeater", noSelect: true, ontap: "itemTap"} - ]} - ], - scrollerName: "scroller", - initComponents: function() { - this.controlParentName = 'flyweight'; - this.inherited(arguments); - //Force the flyweight's client control (MenuItem is default) to activate. This will - //result in a call to processActivatedItem which preps our picker selection logic. - //This is a workaround for changes caused by ENYO-1609 which resulted in ENYO-1611. - this.$.flyweight.$.client.children[0].setActive(true); - }, - create: function() { - this.inherited(arguments); - this.countChanged(); - }, - rendered: function() { - this.inherited(arguments); - this.selectedChanged(); - }, - scrollToSelected: function() { - var n = this.$.flyweight.fetchRowNode(this.selected); - this.getScroller().scrollToNode(n, !this.menuUp); - }, - countChanged: function() { - this.$.flyweight.count = this.count; - }, - processActivatedItem: function(inItem) { - this.item = inItem; - }, - selectedChanged: function(inOld) { - if (!this.item) { - return; - } - if (inOld != null) { - this.item.removeClass("selected"); - this.$.flyweight.renderRow(inOld); - } - var n; - if (this.selected != null) { - this.item.addClass("selected"); - this.$.flyweight.renderRow(this.selected); - // need to remove the class from control to make sure it won't apply to other rows - this.item.removeClass("selected"); - n = this.$.flyweight.fetchRowNode(this.selected); - } - this.doChange({selected: this.selected, content: n && n.textContent || this.item.content}); - }, - itemTap: function(inSender, inEvent) { - this.setSelected(inEvent.rowIndex); - //Send the select event that we want the client to receive. - this.doSelect({selected: this.item, content: this.item.content}); - }, - itemSelect: function(inSender, inEvent) { - //Block all select events that aren't coming from this control. This is to prevent select events from MenuItems since they won't have the correct value in a Flyweight context. - if (inEvent.originator != this) { - return true; - } - } -}); diff --git a/lib/onyx/source/Grabber.js b/lib/onyx/source/Grabber.js deleted file mode 100644 index 0fd74f5..0000000 --- a/lib/onyx/source/Grabber.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - A control styled to indicate that an object can be grabbed and moved. It - should only be used in this limited context--to indicate that dragging the - object will result in movement. - - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Grabber", ondragstart: "grabberDragstart", - ondrag: "grabberDrag", ondragfinish: "grabberDragFinish"}, - {kind: "onyx.Button", content: "More stuff"} - ]} - - When using a Grabber inside a Fittable control, be sure to set "noStretch: true" - on the Fittable or else give it an explicit height. Otherwise, the Grabber - may not be visible. -*/ -enyo.kind({ - name: "onyx.Grabber", - classes: "onyx-grabber" -}); \ No newline at end of file diff --git a/lib/onyx/source/Groupbox.js b/lib/onyx/source/Groupbox.js deleted file mode 100644 index 1b41d5b..0000000 --- a/lib/onyx/source/Groupbox.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - _onyx.Groupbox_ displays rows of controls as a vertically-stacked group. It - is designed to have container controls as its children, with each container - representing a row in the Groupbox. - - A header may be added by specifying an - onyx.GroupboxHeader as the first control - in the Groupbox, e.g.: - - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "Sounds"}, - {components: [ - {content: "System Sounds"}, - {kind: "onyx.ToggleButton", value: true} - ]}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input"} - ]} - ]} - ]} - -*/ -enyo.kind({ - name: "onyx.Groupbox", - classes: "onyx-groupbox" -}); - -/** - A GroupboxHeader is designed to be placed inside an onyx.Groupbox. When a header for a group is desired, - make a GroupboxHeader the first control inside a Groupbox. - - {kind: "onyx.Groupbox", components: [ - {kind: "onyx.GroupboxHeader", content: "Sounds"}, - {content: "Yawn"}, - {content: "Beep"} - ]} -*/ -enyo.kind({ - name: "onyx.GroupboxHeader", - classes: "onyx-groupbox-header" -}); \ No newline at end of file diff --git a/lib/onyx/source/Icon.js b/lib/onyx/source/Icon.js deleted file mode 100644 index d139076..0000000 --- a/lib/onyx/source/Icon.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - A control that displays an icon. The icon image is specified by setting the - *src* property to a URL. - - In Onyx, icons have a size of 32x32 pixels. Since the icon image is applied - as a CSS background, the height and width of an icon must be set if an image - of a different size is used. - - {kind: "onyx.Icon", src: "images/search.png"} - - When an icon should act like a button, use an onyx.IconButton. - -*/ -enyo.kind({ - name: "onyx.Icon", - published: { - //* URL specifying path to icon image - src: "", - //* When true, icon is shown as disabled. - disabled: false - }, - classes: "onyx-icon", - //* @protected - create: function() { - this.inherited(arguments); - if (this.src) { - this.srcChanged(); - } - this.disabledChanged(); - }, - disabledChanged: function() { - this.addRemoveClass("disabled", this.disabled); - }, - srcChanged: function() { - this.applyStyle("background-image", "url(" + enyo.path.rewrite(this.src) + ")"); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/IconButton.js b/lib/onyx/source/IconButton.js deleted file mode 100644 index 35bf33c..0000000 --- a/lib/onyx/source/IconButton.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - _onyx.IconButton_ is an icon that acts like a button. The icon image is - specified by setting the _src_ property to a URL. - - If you want to combine an icon with text inside a button, use an - onyx.Icon inside an - onyx.Button. - - The image associated with the _src_ property of the IconButton is assumed - to be 32x64-pixel strip with the top half showing the button's normal state - and the bottom half showing its state when hovered-over or active. - - For more information, see the documentation on - [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer - Guide. -*/ -enyo.kind({ - name: "onyx.IconButton", - kind: "onyx.Icon", - published: { - //* Used when the IconButton is part of a enyo.Group, true - //* to indicate that this is the active button of the group, false otherwise. - active: false - }, - classes: "onyx-icon-button", - //* @protected - create: function() { - //workaround for FirefoxOS which doesn't support :active:hover css selectors - if(enyo.platform.firefoxOS) { - this.handlers.ondown = "down"; - this.handlers.onleave = "leave"; - } - this.inherited(arguments); - }, - down: function(inSender, inEvent) { - this.addClass("pressed"); - }, - leave: function(inSender, inEvent) { - this.removeClass("pressed"); - }, - rendered: function() { - this.inherited(arguments); - this.activeChanged(); - }, - tap: function() { - if (this.disabled) { - return true; - } - this.setActive(true); - }, - activeChanged: function() { - this.bubble("onActivate"); - } -}); diff --git a/lib/onyx/source/Input.js b/lib/onyx/source/Input.js deleted file mode 100644 index 8c6ed90..0000000 --- a/lib/onyx/source/Input.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - _onyx.Input_ is an Onyx-styled input control, derived from - enyo.Input. Typically, an _onyx.Input_ is placed - inside an onyx.InputDecorator, which - provides styling, e.g.: - - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Enter some text...", onchange: "inputChange"} - ]} - - For more information, see the documentation on - [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "onyx.Input", - kind: "enyo.Input", - classes: "onyx-input" -}); diff --git a/lib/onyx/source/InputDecorator.js b/lib/onyx/source/InputDecorator.js deleted file mode 100644 index bda0e86..0000000 --- a/lib/onyx/source/InputDecorator.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - _onyx.InputDecorator_ is a control that provides input styling. Any controls - in the InputDecorator will appear to be inside an area styled as an input. - Usually, an InputDecorator surrounds an onyx.Input. - - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input"} - ]} - - Other controls, such as buttons, may be placed to the right or left of the - input control, e.g.: - - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.IconButton", src: "search.png"}, - {kind: "onyx.Input"}, - {kind: "onyx.IconButton", src: "cancel.png"} - ]} - - Note that the InputDecorator fits around the content inside it. If the - decorator is sized, then its contents will likely need to be sized as well. - - {kind: "onyx.InputDecorator", style: "width: 500px;", components: [ - {kind: "onyx.Input", style: "width: 100%;"} - ]} -*/ -enyo.kind({ - name: "onyx.InputDecorator", - kind: "enyo.ToolDecorator", - tag: "label", - classes: "onyx-input-decorator", - published:{ - //* Set to true to make the input look focused when it's not. - alwaysLooksFocused:false - }, - //* @protected - handlers: { - onDisabledChange: "disabledChange", - onfocus: "receiveFocus", - onblur: "receiveBlur" - }, - create:function() { - this.inherited(arguments); - this.updateFocus(false); - }, - alwaysLooksFocusedChanged:function(oldValue) { - this.updateFocus(this.focus); - }, - updateFocus:function(focus) { - this.focused = focus; - this.addRemoveClass("onyx-focused", this.alwaysLooksFocused || this.focused); - }, - receiveFocus: function() { - this.updateFocus(true); - }, - receiveBlur: function() { - this.updateFocus(false); - }, - disabledChange: function(inSender, inEvent) { - this.addRemoveClass("onyx-disabled", inEvent.originator.disabled); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/IntegerPicker.js b/lib/onyx/source/IntegerPicker.js deleted file mode 100644 index 1e19644..0000000 --- a/lib/onyx/source/IntegerPicker.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - _onyx.IntegerPicker_, a subkind of onyx.Picker, - is used to display a list of integers that can be selected, ranging from - _min_ to _max_. It is meant to be used in conjunction with an - onyx.PickerDecorator. The decorator - loosely couples the picker with an - onyx.PickerButton--a button that, when - tapped, shows the picker. Once an item is selected, the list of items - closes, but the item stays selected and the PickerButton displays the choice - that was made. - - To initialize the IntegerPicker to a particular value, set the _value_ - property to the integer that should be selected. - - {kind: "onyx.PickerDecorator", components: [ - {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton - {kind: "onyx.IntegerPicker", min: 0, max: 25, value: 5} - ]} - - Each item in the list is an onyx.MenuItem, so - an application may listen for an _onSelect_ event with the item to determine - which picker item was selected. - - For more information, see the documentation on - Pickers in the - Enyo Developer Guide. - */ -enyo.kind({ - name: "onyx.IntegerPicker", - kind: "onyx.Picker", - published: { - value: 0, - min: 0, - max: 9 - }, - //* @protected - create: function() { - this.inherited(arguments); - this.rangeChanged(); - }, - minChanged: function() { - this.destroyClientControls(); - this.rangeChanged(); - this.render(); - }, - maxChanged: function() { - this.destroyClientControls(); - this.rangeChanged(); - this.render(); - }, - rangeChanged: function() { - for (var i=this.min; i<=this.max; i++) { - this.createComponent({content: i, active: (i===this.value) ? true : false}); - } - }, - valueChanged: function(inOld) { - var controls = this.getClientControls(); - var len = controls.length; - // Validate our value - this.value = this.value >= this.min && this.value <= this.max ? this.value : this.min; - for (var i=0; ionyx.Popup that - displays a list of onyx.MenuItem objects and - looks like a popup menu. It is meant to be used in conjunction with an - onyx.MenuDecorator. The decorator couples - the menu with an activating control, which may be a button or any other - control with an _onActivate_ event. When the control is activated, the menu - shows itself in the correct position relative to the activator. - - {kind: "onyx.MenuDecorator", components: [ - {content: "Show menu"}, - {kind: "onyx.Menu", components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "Label", classes: "onyx-menu-label"}, - {content: "3"}, - ]} - ]} - - For more information, see the documentation on - Menus in the Enyo - Developer Guide. - */ -enyo.kind({ - name: "onyx.Menu", - kind: "onyx.Popup", - //* If true, prevents controls outside the menu from receiving events while - //* the menu is showing - modal: true, - defaultKind: "onyx.MenuItem", - classes: "onyx-menu", - published: { - //* Maximum height of the menu - maxHeight: 200, - //* Toggle scrolling - scrolling: true - }, - handlers: { - onActivate: "itemActivated", - onRequestShowMenu: "requestMenuShow", - onRequestHideMenu: "requestHide" - }, - childComponents: [ - {name: "client", kind: "enyo.Scroller", strategyKind: "TouchScrollStrategy"} - ], - showOnTop: false, - scrollerName: "client", - create: function() { - this.inherited(arguments); - this.maxHeightChanged(); - }, - initComponents: function() { - if (this.scrolling) { - this.createComponents(this.childComponents, {isChrome: true}); - } - this.inherited(arguments); - }, - getScroller: function() { - return this.$[this.scrollerName]; - }, - maxHeightChanged: function() { - if (this.scrolling) { - this.getScroller().setMaxHeight(this.maxHeight + "px"); - } - }, - itemActivated: function(inSender, inEvent) { - inEvent.originator.setActive(false); - return true; - }, - showingChanged: function() { - this.inherited(arguments); - if (this.scrolling) { - this.getScroller().setShowing(this.showing); - } - this.adjustPosition(true); - }, - requestMenuShow: function(inSender, inEvent) { - if (this.floating) { - var n = inEvent.activator.hasNode(); - if (n) { - var r = this.activatorOffset = this.getPageOffset(n); - this.applyPosition({top: r.top + (this.showOnTop ? 0 : r.height), left: r.left, width: r.width}); - } - } - this.show(); - return true; - }, - applyPosition: function(inRect) { - var s = ""; - for (var n in inRect) { - s += (n + ":" + inRect[n] + (isNaN(inRect[n]) ? "; " : "px; ")); - } - this.addStyles(s); - }, - getPageOffset: function(inNode) { - // getBoundingClientRect returns top/left values which are relative to the viewport and not absolute - var r = inNode.getBoundingClientRect(); - - // IE8 doesn't return window.page{X/Y}Offset & r.{height/width} - // FIXME: Perhaps use an alternate universal method instead of conditionals - var pageYOffset = (window.pageYOffset === undefined) ? document.documentElement.scrollTop : window.pageYOffset; - var pageXOffset = (window.pageXOffset === undefined) ? document.documentElement.scrollLeft : window.pageXOffset; - var rHeight = (r.height === undefined) ? (r.bottom - r.top) : r.height; - var rWidth = (r.width === undefined) ? (r.right - r.left) : r.width; - - return {top: r.top + pageYOffset, left: r.left + pageXOffset, height: rHeight, width: rWidth}; - }, - //* @protected - /* Adjusts the menu position to fit inside the current window size. - /* Note that we aren't currently adjusting picker scroller heights. - */ - adjustPosition: function() { - if (this.showing && this.hasNode()) { - if (this.scrolling && !this.showOnTop) { - this.getScroller().setMaxHeight(this.maxHeight+"px"); - } - this.removeClass("onyx-menu-up"); - - //reset the left position before we get the bounding rect for proper horizontal calculation - if (!this.floating) { - this.applyPosition({left: "auto"}); - } - - var b = this.node.getBoundingClientRect(); - var bHeight = (b.height === undefined) ? (b.bottom - b.top) : b.height; - var innerHeight = (window.innerHeight === undefined) ? document.documentElement.clientHeight : window.innerHeight; - var innerWidth = (window.innerWidth === undefined) ? document.documentElement.clientWidth : window.innerWidth; - - //position the menu above the activator if it's getting cut off, but only if there's more room above than below - this.menuUp = (b.top + bHeight > innerHeight) && ((innerHeight - b.bottom) < (b.top - bHeight)); - this.addRemoveClass("onyx-menu-up", this.menuUp); - - //if floating, adjust the vertical positioning - if (this.floating) { - var r = this.activatorOffset; - //if the menu doesn't fit below the activator, move it up - if (this.menuUp) { - this.applyPosition({top: (r.top - bHeight + (this.showOnTop ? r.height : 0)), bottom: "auto"}); - } - else { - //if the top of the menu is above the top of the activator and there's room to move it down, do so - if ((b.top < r.top) && (r.top + (this.showOnTop ? 0 : r.height) + bHeight < innerHeight)) - { - this.applyPosition({top: r.top + (this.showOnTop ? 0 : r.height), bottom: "auto"}); - } - } - } - - //adjust the horizontal positioning to keep the menu from being cut off on the right - if ((b.right) > innerWidth) { - if (this.floating){ - this.applyPosition({left:innerWidth-b.width}); - } else { - this.applyPosition({left: -(b.right - innerWidth)}); - } - } - - //finally prevent the menu from being cut off on the left - if (b.left < 0) { - if (this.floating){ - this.applyPosition({left: 0, right:"auto"}); - } else { - //handle the situation where a non-floating menu is right or left aligned - if (this.getComputedStyleValue("right") == "auto"){ - this.applyPosition({left:-b.left}); - } else { - this.applyPosition({right:b.left}); - } - } - } - - //adjust the scroller height based on room available - only doing this for menus currently - if (this.scrolling && !this.showOnTop){ - b = this.node.getBoundingClientRect(); //update to the current menu position - var scrollerHeight; - if (this.menuUp){ - scrollerHeight = (this.maxHeight < b.bottom) ? this.maxHeight : b.bottom; - } else { - scrollerHeight = ((b.top + this.maxHeight) < innerHeight) ? this.maxHeight : (innerHeight - b.top); - } - this.getScroller().setMaxHeight(scrollerHeight+"px"); - } - } - }, - resizeHandler: function() { - this.inherited(arguments); - this.adjustPosition(); - }, - requestHide: function(){ - this.setShowing(false); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/MenuDecorator.js b/lib/onyx/source/MenuDecorator.js deleted file mode 100644 index 631bcb1..0000000 --- a/lib/onyx/source/MenuDecorator.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - A control that activates an onyx.Menu. It loosely - couples the Menu with an activating control, which may be a button or any - other control with an _onActivate_ event. The decorator must surround both - the activating control and the menu itself. When the control is activated, - the menu shows itself in the correct position relative to the activator. - - {kind: "onyx.MenuDecorator", components: [ - {content: "Show menu"}, - {kind: "onyx.Menu", components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "Label", classes: "onyx-menu-label"}, - {content: "3"}, - ]} - ]} - */ -enyo.kind({ - name: "onyx.MenuDecorator", - kind: "onyx.TooltipDecorator", - defaultKind: "onyx.Button", - // selection on ios prevents tap events, so avoid. - classes: "onyx-popup-decorator enyo-unselectable", - //* @protected - handlers: { - onActivate: "activated", - onHide: "menuHidden" - }, - activated: function(inSender, inEvent) { - this.requestHideTooltip(); - if (inEvent.originator.active) { - this.menuActive = true; - this.activator = inEvent.originator; - this.activator.addClass("active"); - this.requestShowMenu(); - } - }, - requestShowMenu: function() { - this.waterfallDown("onRequestShowMenu", {activator: this.activator}); - }, - requestHideMenu: function() { - this.waterfallDown("onRequestHideMenu"); - }, - menuHidden: function() { - this.menuActive = false; - if (this.activator) { - this.activator.setActive(false); - this.activator.removeClass("active"); - } - }, - enter: function(inSender) { - if (!this.menuActive) { - this.inherited(arguments); - } - }, - leave: function(inSender, inEvent) { - if (!this.menuActive) { - this.inherited(arguments); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/source/MenuItem.js b/lib/onyx/source/MenuItem.js deleted file mode 100644 index a7b90a4..0000000 --- a/lib/onyx/source/MenuItem.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - _MenuItem_ is a button styled to look like a menu item, intended for use in - an onyx.Menu. When the MenuItem is tapped, it - tells the menu to hide itself and sends an _onSelect_ event with its - content and a reference to itself. This event and its properties may be - received by a client application to determine which menu item was selected. - - enyo.kind({ - handlers: { - onSelect: "itemSelected" - }, - components: [ - {kind: "onyx.MenuDecorator", components: [ - {content: "Open Menu (floating)"}, - {kind: "onyx.Menu", floating: true, components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "Label", classes: "onyx-menu-label"}, - {content: "3"}, - ]} - ]} - ], - itemSelected: function(inSender, inEvent) { - enyo.log("Menu Item Selected: " + inEvent.originator.content); - } - }) - */ -enyo.kind({ - name: "onyx.MenuItem", - kind: "enyo.Button", - events: { - /** - Fires when the menu item is selected. - - _inEvent.selected_ contains a reference to the menu item. - - _inEvent.content_ contains the menu item's content. - */ - onSelect: "", - /** - Fires when the content of an item changes. - - _inEvent.content_ contains the content of the item. - */ - onItemContentChange: "" - }, - //* @protected - classes: "onyx-menu-item", - tag: "div", - create: function(){ - this.inherited(arguments); - if (this.active){ - this.bubble("onActivate"); - } - }, - tap: function(inSender) { - this.inherited(arguments); - this.bubble("onRequestHideMenu"); - this.doSelect({selected:this, content:this.content}); - }, - contentChanged: function(inOld){ - this.inherited(arguments); - this.doItemContentChange({content: this.content}); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/MoreToolbar.js b/lib/onyx/source/MoreToolbar.js deleted file mode 100644 index 8a66470..0000000 --- a/lib/onyx/source/MoreToolbar.js +++ /dev/null @@ -1,156 +0,0 @@ -/** - _onyx.MoreToolbar_ extends enyo.Control, - providing a toolbar that can adapt to different screen sizes by moving - overflowing controls and content into an onyx.Menu. - - {kind: "onyx.MoreToolbar", components: [ - {content: "More Toolbar", unmoveable: true}, - {kind: "onyx.Button", content: "Alpha"}, - {kind: "onyx.Button", content: "Beta"}, - {kind: "onyx.Button", content: "Gamma", unmoveable: true}, - {kind: "onyx.Button", content: "Epsilon"} - ]}, - - You may prevent a control from being moved into the menu by setting its - _unmoveable_ property to true (the default is false). - - For more information, see the documentation on - Toolbars in the - Enyo Developer Guide. -*/ - -enyo.kind({ - name: "onyx.MoreToolbar", - //* @public - classes: "onyx-toolbar onyx-more-toolbar", - //* Style class to be applied to the menu - menuClass: "", - //* Style class to be applied to individual controls moved from the toolbar to the menu - movedClass: "", - //* @protected - layoutKind: "FittableColumnsLayout", - noStretch: true, - handlers: { - onHide: "reflow" - }, - published: { - //* Layout kind that will be applied to the client controls. - clientLayoutKind: "FittableColumnsLayout" - }, - tools: [ - {name: "client", noStretch:true, fit: true, classes: "onyx-toolbar-inline"}, - {name: "nard", kind: "onyx.MenuDecorator", showing: false, onActivate: "activated", components: [ - {kind: "onyx.IconButton", classes: "onyx-more-button"}, - {name: "menu", kind: "onyx.Menu", scrolling:false, classes: "onyx-more-menu"} - ]} - ], - initComponents: function() { - if(this.menuClass && this.menuClass.length>0 && !this.$.menu.hasClass(this.menuClass)) { - this.$.menu.addClass(this.menuClass); - } - this.createChrome(this.tools); - this.inherited(arguments); - this.$.client.setLayoutKind(this.clientLayoutKind); - }, - clientLayoutKindChanged: function(){ - this.$.client.setLayoutKind(this.clientLayoutKind); - }, - reflow: function() { - this.inherited(arguments); - if (this.isContentOverflowing()) { - this.$.nard.show(); - if (this.popItem()) { - this.reflow(); - } - } else if (this.tryPushItem()) { - this.reflow(); - } else if (!this.$.menu.children.length) { - this.$.nard.hide(); - this.$.menu.hide(); - } - }, - activated: function(inSender, inEvent) { - this.addRemoveClass("active",inEvent.originator.active); - }, - popItem: function() { - var c = this.findCollapsibleItem(); - if (c) { - //apply movedClass is needed - if(this.movedClass && this.movedClass.length>0 && !c.hasClass(this.movedClass)) { - c.addClass(this.movedClass); - } - // passing null to add child to the front of the control list - this.$.menu.addChild(c, null); - var p = this.$.menu.hasNode(); - if (p && c.hasNode()) { - c.insertNodeInParent(p); - } - return true; - } - }, - pushItem: function() { - var c$ = this.$.menu.children; - var c = c$[0]; - if (c) { - //remove any applied movedClass - if(this.movedClass && this.movedClass.length>0 && c.hasClass(this.movedClass)) { - c.removeClass(this.movedClass); - } - this.$.client.addChild(c); - var p = this.$.client.hasNode(); - if (p && c.hasNode()) { - var nextChild; - var currIndex; - for(var i=0; i this.$.client.node.clientWidth); - return ((n.offsetLeft + n.offsetWidth) > this.$.client.node.clientWidth); - } - } - }, - findCollapsibleItem: function() { - var c$ = this.$.client.children; - for (var i=c$.length-1; (c=c$[i]); i--) { - if (!c.unmoveable) { - return c; - } else { - if(c.toolbarIndex===undefined) { - c.toolbarIndex = i; - } - } - } - } -}); diff --git a/lib/onyx/source/Picker.js b/lib/onyx/source/Picker.js deleted file mode 100644 index 4cd1e9f..0000000 --- a/lib/onyx/source/Picker.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - _onyx.Picker_, a subkind of onyx.Menu, is used to - display a list of items that can be selected. It is meant to be used in - conjunction with an onyx.PickerDecorator. - The decorator loosely couples the picker with an - onyx.PickerButton--a button that, when - tapped, shows the picker. Once an item is selected, the list of items closes, - but the item stays selected and the PickerButton displays the choice that - was made. - - To initialize the Picker to a particular value, set the _active_ property to - true for the item that should be selected. - - {kind: "onyx.PickerDecorator", components: [ - {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton - {kind: "onyx.Picker", components: [ - {content: "Gmail", active: true}, - {content: "Yahoo"}, - {content: "Outlook"}, - {content: "Hotmail"} - ]} - ]} - - Each item in the list is an onyx.MenuItem, so - an _onSelect_ event with the item can be listened to by a client application - to determine which picker item was selected. - - For more information, see the documentation on - Pickers in the - Enyo Developer Guide. - */ -enyo.kind({ - name: "onyx.Picker", - kind: "onyx.Menu", - classes: "onyx-picker enyo-unselectable", - published: { - //* Currently selected item, if any - selected: null - }, - events: { - /** - Fires when the currently selected item changes. - - _inEvent.selected_ contains the currently selected item. - - _inEvent.content_ contains the content of the currently selected item. - */ - onChange: "" - }, - handlers: { - onItemContentChange: 'itemContentChange' - }, - /** - Set to true to render the picker in a floating layer outside of other - controls. This can be used to guarantee that the picker will be shown - on top of other controls. - */ - floating: true, - //* @protected - // overrides default value from onyx.Menu - showOnTop: true, - initComponents: function() { - this.setScrolling(true); - this.inherited(arguments); - }, - showingChanged: function() { - this.getScroller().setShowing(this.showing); - this.inherited(arguments); - if (this.showing && this.selected) { - this.scrollToSelected(); - } - }, - scrollToSelected: function() { - this.getScroller().scrollToControl(this.selected, !this.menuUp); - }, - itemActivated: function(inSender, inEvent) { - this.processActivatedItem(inEvent.originator); - return this.inherited(arguments); - }, - processActivatedItem: function(inItem) { - if (inItem.active) { - this.setSelected(inItem); - } - }, - selectedChanged: function(inOld) { - if (inOld) { - inOld.removeClass("selected"); - } - if (this.selected) { - this.selected.addClass("selected"); - this.doChange({selected: this.selected, content: this.selected.content}); - } - }, - itemContentChange: function(inSender, inEvent){ - if(inEvent.originator == this.selected){ - this.doChange({selected: this.selected, content: this.selected.content}); - } - }, - resizeHandler: function() { - this.inherited(arguments); - this.adjustPosition(); - } -}); diff --git a/lib/onyx/source/PickerButton.js b/lib/onyx/source/PickerButton.js deleted file mode 100644 index f1c9d14..0000000 --- a/lib/onyx/source/PickerButton.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - _onyx.PickerButton_ is a button that, when tapped, shows an - onyx.Picker. Once an item is selected, the list - of items closes, but the item stays selected and the PickerButton displays - the choice that was made. - - For more information, see the documentation on - [Pickers](https://github.com/enyojs/enyo/wiki/Pickers) in the Enyo Developer - Guide. - */ -enyo.kind({ - name: "onyx.PickerButton", - kind: "onyx.Button", - handlers: { - onChange: "change" - }, - change: function(inSender, inEvent) { - if (inEvent.content !== undefined){ - this.setContent(inEvent.content); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/source/PickerDecorator.js b/lib/onyx/source/PickerDecorator.js deleted file mode 100644 index bf248d9..0000000 --- a/lib/onyx/source/PickerDecorator.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - A control that activates an onyx.Picker. It - loosely couples the Picker with an activating - onyx.PickerButton. The decorator must - surround both the activating button and the picker itself. When the button - is activated, the picker shows itself in the correct position relative to - the activator. - - {kind: "onyx.PickerDecorator", components: [ - {}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton - {kind: "onyx.Picker", components: [ - {content: "Gmail", active: true}, - {content: "Yahoo"}, - {content: "Outlook"}, - {content: "Hotmail"} - ]} - ]} - */ -enyo.kind({ - name: "onyx.PickerDecorator", - kind: "onyx.MenuDecorator", - classes: "onyx-picker-decorator", - defaultKind: "onyx.PickerButton", - handlers: { - onChange: "change" - }, - change: function(inSender, inEvent) { - this.waterfallDown("onChange", inEvent); - } -}); diff --git a/lib/onyx/source/Popup.js b/lib/onyx/source/Popup.js deleted file mode 100644 index cb40ef5..0000000 --- a/lib/onyx/source/Popup.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - _onyx.Popup_ is an enhanced [enyo.Popup](http://enyojs.com/api/#enyo.Popup) - with built-in scrim and z-index handling. - - To avoid obscuring popup contents, scrims require the dialog to be floating; - otherwise, they won't render. A modal popup will get a transparent scrim - unless the popup isn't floating. To get a translucent scrim when modal, - specify _scrim: true, scrimWhenModal: false_. - - For more information, see the documentation on - [Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer - Guide. -*/ -enyo.kind({ - name: "onyx.Popup", - kind: "Popup", - classes: "onyx-popup", - published: { - /** - Determines whether a scrim will appear when the dialog is modal. - Note that modal scrims are transparent, so you won't see them. - */ - scrimWhenModal: true, - //* Determines whether or not to display a scrim. Only displays scrims - //* when floating. - scrim: false, - /** - Optional class name to apply to the scrim. Be aware that the scrim - is a singleton and you will be modifying the scrim instance used for - other popups. - */ - scrimClassName: "" - }, - //* @protected - statics: { count: 0 }, - defaultZ: 120, - showingChanged: function() { - if(this.showing) { - onyx.Popup.count++; - this.applyZIndex(); - } - else { - if(onyx.Popup.count > 0) { - onyx.Popup.count--; - } - } - this.showHideScrim(this.showing); - this.inherited(arguments); - }, - showHideScrim: function(inShow) { - if (this.floating && (this.scrim || (this.modal && this.scrimWhenModal))) { - var scrim = this.getScrim(); - if (inShow) { - // move scrim to just under the popup to obscure rest of screen - var i = this.getScrimZIndex(); - this._scrimZ = i; - scrim.showAtZIndex(i); - } else { - scrim.hideAtZIndex(this._scrimZ); - } - enyo.call(scrim, "addRemoveClass", [this.scrimClassName, scrim.showing]); - } - }, - getScrimZIndex: function() { - // Position scrim directly below popup - return this.findZIndex()-1; - }, - getScrim: function() { - // show a transparent scrim for modal popups if scrimWhenModal is true - // if scrim is true, then show a regular scrim. - if (this.modal && this.scrimWhenModal && !this.scrim) { - return onyx.scrimTransparent.make(); - } - return onyx.scrim.make(); - }, - applyZIndex: function() { - // Adjust the zIndex so that popups will properly stack on each other. - this._zIndex = onyx.Popup.count * 2 + this.findZIndex() + 1; - // leave room for scrim - this.applyStyle("z-index", this._zIndex); - }, - findZIndex: function() { - // a default z value - var z = this.defaultZ; - if (this._zIndex) { - z = this._zIndex; - } else if (this.hasNode()) { - // Re-use existing zIndex if it has one - z = Number(enyo.dom.getComputedStyleValue(this.node, "z-index")) || z; - } - return (this._zIndex = z); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/ProgressBar.js b/lib/onyx/source/ProgressBar.js deleted file mode 100644 index 084e317..0000000 --- a/lib/onyx/source/ProgressBar.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - _onyx.ProgressBar_ is a control that shows the current progress of a - process in a horizontal bar. - - {kind: "onyx.ProgressBar", progress: 10} - - To animate progress changes, call the _animateProgressTo_ method: - - this.$.progressBar.animateProgressTo(50); - - You may customize the color of the bar by applying a style via the - _barClasses_ property, e.g.: - - {kind: "onyx.ProgressBar", barClasses: "onyx-dark"} - - For more information, see the documentation on - Progress Indicators - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.ProgressBar", - classes: "onyx-progress-bar", - published: { - //* Current position of progress bar - progress: 0, - //* Minimum progress value (i.e., no progress made) - min: 0, - //* Maximum progress value (i.e., process complete) - max: 100, - //* CSS classes to apply to progress bar - barClasses: "", - //* If true, stripes are shown in progress bar - showStripes: true, - //* If true (and _showStripes_ is true), stripes shown in progress bar - //* are animated - animateStripes: true, - //* Value increment that a sliders can be "snapped to" in either direction - increment: 0 - }, - events: { - //* Fires when progress bar finishes animating to a position. - onAnimateProgressFinish: "" - }, - //* @protected - components: [ - {name: "progressAnimator", kind: "Animator", onStep: "progressAnimatorStep", onEnd: "progressAnimatorComplete"}, - {name: "bar", classes: "onyx-progress-bar-bar"} - ], - create: function() { - this.inherited(arguments); - this.progressChanged(); - this.barClassesChanged(); - this.showStripesChanged(); - this.animateStripesChanged(); - }, - barClassesChanged: function(inOld) { - this.$.bar.removeClass(inOld); - this.$.bar.addClass(this.barClasses); - }, - showStripesChanged: function() { - this.$.bar.addRemoveClass("striped", this.showStripes); - }, - animateStripesChanged: function() { - this.$.bar.addRemoveClass("animated", this.animateStripes); - }, - progressChanged: function() { - this.progress = this.clampValue(this.min, this.max, this.progress); - var p = this.calcPercent(this.progress); - this.updateBarPosition(p); - }, - calcIncrement: function(inValue) { - return (Math.round(inValue / this.increment) * this.increment); - }, - clampValue: function(inMin, inMax, inValue) { - return Math.max(inMin, Math.min(inValue, inMax)); - }, - calcRatio: function(inValue) { - return (inValue - this.min) / (this.max - this.min); - }, - calcPercent: function(inValue) { - return this.calcRatio(inValue) * 100; - }, - updateBarPosition: function(inPercent) { - this.$.bar.applyStyle("width", inPercent + "%"); - }, - //* @public - //* Animates progress to the given value. - animateProgressTo: function(inValue) { - this.$.progressAnimator.play({ - startValue: this.progress, - endValue: inValue, - node: this.hasNode() - }); - }, - //* @protected - progressAnimatorStep: function(inSender) { - this.setProgress(inSender.value); - return true; - }, - progressAnimatorComplete: function(inSender) { - this.doAnimateProgressFinish(inSender); - return true; - } -}); diff --git a/lib/onyx/source/ProgressButton.js b/lib/onyx/source/ProgressButton.js deleted file mode 100644 index 8bbef24..0000000 --- a/lib/onyx/source/ProgressButton.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - _onyx.ProgressButton_ is a progress bar that has a cancel button on the - right and may have other controls inside of it. - - {kind: "onyx.ProgressButton"}, - {kind: "onyx.ProgressButton", barClasses: "onyx-light", progress: 20, components: [ - {content: "0"}, - {content: "100", style: "float: right;"} - ]} - - For more information, see the documentation on - Progress Indicators - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.ProgressButton", - kind: "onyx.ProgressBar", - classes: "onyx-progress-button", - events: { - //* Fires when cancel button is tapped. - onCancel: "" - }, - //* @protected - components: [ - {name: "progressAnimator", kind: "Animator", onStep: "progressAnimatorStep", onEnd: "progressAnimatorComplete"}, - {name: "bar", classes: "onyx-progress-bar-bar onyx-progress-button-bar"}, - {name: "client", classes: "onyx-progress-button-client"}, - {kind: "onyx.Icon", src: "$lib/onyx/images/progress-button-cancel.png", classes: "onyx-progress-button-icon", ontap: "cancelTap"} - ], - cancelTap: function() { - this.doCancel(); - } -}); diff --git a/lib/onyx/source/RadioButton.js b/lib/onyx/source/RadioButton.js deleted file mode 100644 index 590cb0d..0000000 --- a/lib/onyx/source/RadioButton.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - A radio button designed for use within an - onyx.RadioGroup. - - For more information, see the documentation on - [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer - Guide. -*/ -enyo.kind({ - name: "onyx.RadioButton", - kind: "Button", - classes: "onyx-radiobutton" -}); diff --git a/lib/onyx/source/RadioGroup.js b/lib/onyx/source/RadioGroup.js deleted file mode 100644 index fa7b8a3..0000000 --- a/lib/onyx/source/RadioGroup.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - A group of onyx.RadioButton objects - laid out horizontally. Within the same radio group, tapping on one radio button - will release any previously tapped radio button. - - {kind: "onyx.RadioGroup", components: [ - {content: "foo", active: true}, - {content: "bar"}, - {content: "baz"} - ]} -*/ -enyo.kind({ - name: "onyx.RadioGroup", - kind: "Group", - defaultKind: "onyx.RadioButton", - //* @protected - // set to true to provide radio button behavior - highlander: true -}); - diff --git a/lib/onyx/source/RangeSlider.js b/lib/onyx/source/RangeSlider.js deleted file mode 100644 index 933bc44..0000000 --- a/lib/onyx/source/RangeSlider.js +++ /dev/null @@ -1,227 +0,0 @@ -/** - _onyx.RangeSlider_ is a control that combines a horizontal slider with two - control knobs. The user may drag the knobs to select a desired range of - values. - - {kind: "onyx.RangeSlider", rangeMin: 100, rangeMax: 500, - rangeStart: 200, rangeEnd: 400, interval: 20} - - _onChanging_ events are fired while the control knobs are being dragged, and - an _onChange_ event is fired when the position is set by finishing a drag. -*/ -enyo.kind({ - name: "onyx.RangeSlider", - kind: "onyx.ProgressBar", - classes: "onyx-slider", - published: { - //* @public - //* Minimum slider value - rangeMin: 0, - //* Maximum slider value - rangeMax: 100, - /** - Value of first slider, expressed as an integer between _rangeMin_ - and _rangeMax_ - */ - rangeStart: 0, - /** - Value of second slider, expressed as an integer between _rangeMin_ - and _rangeMax_ - */ - rangeEnd: 100, - //* @protected - // Position of first slider, expressed as an integer between 0 and 100 (percentage) - beginValue: 0, - // Position of second slider, expressed as an integer between 0 and 100 (percentage) - endValue: 0 - }, - //* @public - events: { - /** - Fires when bar position is set. - - _inEvent.value_ contains the new position. - - _inEvent.startChanged_ is a boolean value indicating whether the - first slider (_rangeStart_) triggered the event. - */ - onChange: "", - /** - Fires while control knob is being dragged. - - _inEvent.value_ contains the current position. - */ - onChanging: "" - }, - //* If true, stripes are shown in the slider bar - showStripes: false, - //* If true, labels are shown above each slider knob - showLabels: false, - //* @protected - handlers: { - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish", - ondown: "down" - }, - moreComponents: [ - {name: "startKnob", classes: "onyx-slider-knob"}, - {name: "endKnob", classes: "onyx-slider-knob onyx-range-slider-knob"} - ], - create: function() { - this.inherited(arguments); - this.createComponents(this.moreComponents); - this.initControls(); - }, - rendered: function() { - this.inherited(arguments); - var p = this.calcPercent(this.beginValue); - this.updateBarPosition(p); - }, - initControls: function() { - this.$.bar.applyStyle("position", "relative"); - this.refreshRangeSlider(); - if (this.showLabels) { - this.$.startKnob.createComponent({name: "startLabel", kind: "onyx.RangeSliderKnobLabel"}); - this.$.endKnob.createComponent({name: "endLabel", kind: "onyx.RangeSliderKnobLabel"}); - } - }, - refreshRangeSlider: function() { - // Calculate range percentages, in order to position sliders - this.beginValue = this.calcKnobPercent(this.rangeStart); - this.endValue = this.calcKnobPercent(this.rangeEnd); - this.beginValueChanged(); - this.endValueChanged(); - }, - calcKnobRatio: function(inValue) { - return (inValue - this.rangeMin) / (this.rangeMax - this.rangeMin); - }, - calcKnobPercent: function(inValue) { - return this.calcKnobRatio(inValue) * 100; - }, - beginValueChanged: function(sliderPos) { - if (sliderPos === undefined) { - var p = this.calcPercent(this.beginValue); - this.updateKnobPosition(p, this.$.startKnob); - } - }, - endValueChanged: function(sliderPos) { - if (sliderPos === undefined) { - var p = this.calcPercent(this.endValue); - this.updateKnobPosition(p, this.$.endKnob); - } - }, - calcKnobPosition: function(inEvent) { - var x = inEvent.clientX - this.hasNode().getBoundingClientRect().left; - return (x / this.getBounds().width) * (this.max - this.min) + this.min; - }, - updateKnobPosition: function(inPercent, inControl) { - inControl.applyStyle("left", inPercent + "%"); - this.updateBarPosition(); - }, - updateBarPosition: function() { - if ((this.$.startKnob !== undefined) && (this.$.endKnob !== undefined)) { - var barStart = this.calcKnobPercent(this.rangeStart); - var barWidth = this.calcKnobPercent(this.rangeEnd) - barStart; - this.$.bar.applyStyle("left", barStart + "%"); - this.$.bar.applyStyle("width", barWidth + "%"); - } - }, - calcRangeRatio: function(inValue) { - return ((inValue / 100) * (this.rangeMax - this.rangeMin) + this.rangeMin) - (this.increment/2); - }, - swapZIndex: function(inControl) { - if (inControl === "startKnob") { - this.$.startKnob.applyStyle("z-index", 1); - this.$.endKnob.applyStyle("z-index", 0); - } else if (inControl === "endKnob") { - this.$.startKnob.applyStyle("z-index", 0); - this.$.endKnob.applyStyle("z-index", 1); - } - }, - down: function(inSender, inEvent) { - this.swapZIndex(inSender.name); - }, - dragstart: function(inSender, inEvent) { - if (inEvent.horizontal) { - inEvent.preventDefault(); - this.dragging = true; - return true; - } - }, - drag: function(inSender, inEvent) { - if (this.dragging) { - var knobPos = this.calcKnobPosition(inEvent); - var _val, val, p; - - if ((inSender.name === "startKnob") && (knobPos >= 0)) { - if (((knobPos <= this.endValue) && (inEvent.xDirection === -1)) || (knobPos <= this.endValue)) { - this.setBeginValue(knobPos); - _val = this.calcRangeRatio(this.beginValue); - val = (this.increment) ? this.calcIncrement(_val+0.5*this.increment) : _val; - p = this.calcKnobPercent(val); - this.updateKnobPosition(p, this.$.startKnob); - this.setRangeStart(val); - this.doChanging({value: val}); - } else { - return this.drag(this.$.endKnob, inEvent); - } - } else if ((inSender.name === "endKnob") && (knobPos <= 100)) { - if (((knobPos >= this.beginValue) && (inEvent.xDirection === 1)) || (knobPos >= this.beginValue)) { - this.setEndValue(knobPos); - _val = this.calcRangeRatio(this.endValue); - val = (this.increment) ? this.calcIncrement(_val+0.5*this.increment) : _val; - p = this.calcKnobPercent(val); - this.updateKnobPosition(p, this.$.endKnob); - this.setRangeEnd(val); - this.doChanging({value: val}); - } else { - return this.drag(this.$.startKnob, inEvent); - } - } - return true; - } - }, - dragfinish: function(inSender, inEvent) { - this.dragging = false; - inEvent.preventTap(); - var val; - if (inSender.name === "startKnob") { - val = this.calcRangeRatio(this.beginValue); - this.doChange({value: val, startChanged: true}); - } else if (inSender.name === "endKnob") { - val = this.calcRangeRatio(this.endValue); - this.doChange({value: val, startChanged: false}); - } - return true; - }, - rangeMinChanged: function() { - this.refreshRangeSlider(); - }, - rangeMaxChanged: function() { - this.refreshRangeSlider(); - }, - rangeStartChanged: function() { - this.refreshRangeSlider(); - }, - rangeEndChanged: function() { - this.refreshRangeSlider(); - }, - setStartLabel: function(inContent) { - this.$.startKnob.waterfallDown("onSetLabel", inContent); - }, - setEndLabel: function(inContent) { - this.$.endKnob.waterfallDown("onSetLabel", inContent); - } -}); - -enyo.kind({ - name: "onyx.RangeSliderKnobLabel", - classes: "onyx-range-slider-label", - handlers: { - onSetLabel: "setLabel" - }, - setLabel: function(inSender, inContent) { - this.setContent(inContent); - } -}); diff --git a/lib/onyx/source/RichText.js b/lib/onyx/source/RichText.js deleted file mode 100644 index 86a674b..0000000 --- a/lib/onyx/source/RichText.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - _onyx.RichText_ is an Onyx-styled RichText control, derived from - enyo.RichText. Typically, an _onyx.RichText_ - is placed inside an onyx.InputDecorator, - which provides styling, e.g.: - - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.RichText", style: "width: 100px;", onchange: "inputChange"} - ]} - - For more information, see the documentation on - [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "onyx.RichText", - kind: "enyo.RichText", - classes: "onyx-richtext" -}); diff --git a/lib/onyx/source/Scrim.js b/lib/onyx/source/Scrim.js deleted file mode 100644 index fc12ded..0000000 --- a/lib/onyx/source/Scrim.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - _onyx.Scrim_ provides an overlay that will prevent taps from propagating to - the controls that it covers. A scrim may be "floating" or "non-floating". A - floating scrim will fill the entire viewport, while a non-floating scrim - will be constrained by the dimensions of its container. - - The scrim should have a CSS class of _"onyx-scrim-transparent"_, - _"onyx-scrim-translucent"_, or any other class that has - _"pointer-events: auto"_ in its style properties. - - You may specify the z-index at which you want the scrim to appear by calling - _showAtZIndex_; if you do so, you must call _hideAtZIndex_ with the same - value to hide the scrim. -*/ - -enyo.kind({ - name: "onyx.Scrim", - //* Current visibility state of scrim - showing: false, - classes: "onyx-scrim enyo-fit", - /** - If true, scrim is rendered in a floating layer outside of other - controls. This can be used to guarantee that the scrim will be shown - on top of other controls. - */ - floating: false, - //* @protected - create: function() { - this.inherited(arguments); - this.zStack = []; - if (this.floating) { - this.setParent(enyo.floatingLayer); - } - }, - showingChanged: function() { - // auto render when shown. - if (this.floating && this.showing && !this.hasNode()) { - this.render(); - } - this.inherited(arguments); - //this.addRemoveClass(this.showingClassName, this.showing); - }, - //* @protected - addZIndex: function(inZIndex) { - if (enyo.indexOf(inZIndex, this.zStack) < 0) { - this.zStack.push(inZIndex); - } - }, - removeZIndex: function(inControl) { - enyo.remove(inControl, this.zStack); - }, - //* @public - //* Shows scrim at the specified z-index. Note: If you use _showAtZIndex_, - //* you must call _hideAtZIndex_ to properly unwind the z-index stack. - showAtZIndex: function(inZIndex) { - this.addZIndex(inZIndex); - if (inZIndex !== undefined) { - this.setZIndex(inZIndex); - } - this.show(); - }, - //* Hides scrim at the specified z-index. - hideAtZIndex: function(inZIndex) { - this.removeZIndex(inZIndex); - if (!this.zStack.length) { - this.hide(); - } else { - var z = this.zStack[this.zStack.length-1]; - this.setZIndex(z); - } - }, - //* @protected - // Set scrim to show at `inZIndex` - setZIndex: function(inZIndex) { - this.zIndex = inZIndex; - this.applyStyle("z-index", inZIndex); - }, - make: function() { - return this; - } -}); - -//* @protected -// -// Scrim singleton exposing a subset of Scrim API; -// is replaced with a proper enyo.Scrim instance. -// -enyo.kind({ - name: "onyx.scrimSingleton", - kind: null, - constructor: function(inName, inProps) { - this.instanceName = inName; - enyo.setObject(this.instanceName, this); - this.props = inProps || {}; - }, - make: function() { - var s = new onyx.Scrim(this.props); - enyo.setObject(this.instanceName, s); - return s; - }, - showAtZIndex: function(inZIndex) { - var s = this.make(); - s.showAtZIndex(inZIndex); - }, - // in case somebody does this out of order - hideAtZIndex: enyo.nop, - show: function() { - var s = this.make(); - s.show(); - } -}); - -new onyx.scrimSingleton("onyx.scrim", {floating: true, classes: "onyx-scrim-translucent"}); -new onyx.scrimSingleton("onyx.scrimTransparent", {floating: true, classes: "onyx-scrim-transparent"}); diff --git a/lib/onyx/source/Slider.js b/lib/onyx/source/Slider.js deleted file mode 100644 index 0fccedc..0000000 --- a/lib/onyx/source/Slider.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - _onyx.Slider_ is a control that presents a range of selection options in the - form of a horizontal slider with a control knob. The knob may be tapped and - dragged to the desired location. - - {kind: "onyx.Slider", value: 30} - - _onChanging_ events are fired while the control knob is being dragged, and - an _onChange_ event is fired when the position is set, either by finishing a - drag or by tapping the bar. - - For more information, see the documentation on - Progress Indicators - in the Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.Slider", - kind: "onyx.ProgressBar", - classes: "onyx-slider", - published: { - //* Position of slider, expressed as an integer between 0 and 100, - //* inclusive - value: 0, - //* If true, current progress will be styled differently from rest of bar - lockBar: true, - //* If true, tapping on bar will change current position - tappable: true - }, - events: { - //* Fires when bar position is set. The _value_ property contains the - //* new position. - onChange: "", - //* Fires while control knob is being dragged. The _value_ property - //* contains the current position. - onChanging: "", - //* Fires when animation to a position finishes. - onAnimateFinish: "" - }, - //* If true, stripes are shown in the slider bar - showStripes: false, - //* @protected - handlers: { - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish" - }, - moreComponents: [ - {kind: "Animator", onStep: "animatorStep", onEnd: "animatorComplete"}, - {classes: "onyx-slider-taparea"}, - {name: "knob", classes: "onyx-slider-knob"} - ], - create: function() { - this.inherited(arguments); - //workaround for FirefoxOS which doesn't support :active:hover css selectors - if(enyo.platform.firefoxOS) { - this.moreComponents[2].ondown = "down"; - this.moreComponents[2].onleave = "leave"; - } - this.createComponents(this.moreComponents); - this.valueChanged(); - }, - valueChanged: function() { - this.value = this.clampValue(this.min, this.max, this.value); - var p = this.calcPercent(this.value); - this.updateKnobPosition(p); - if (this.lockBar) { - this.setProgress(this.value); - } - }, - updateKnobPosition: function(inPercent) { - this.$.knob.applyStyle("left", inPercent + "%"); - }, - calcKnobPosition: function(inEvent) { - var x = inEvent.clientX - this.hasNode().getBoundingClientRect().left; - return (x / this.getBounds().width) * (this.max - this.min) + this.min; - }, - dragstart: function(inSender, inEvent) { - if (inEvent.horizontal) { - inEvent.preventDefault(); - this.dragging = true; - return true; - } - }, - drag: function(inSender, inEvent) { - if (this.dragging) { - var v = this.calcKnobPosition(inEvent); - v = (this.increment) ? this.calcIncrement(v) : v; - this.setValue(v); - this.doChanging({value: this.value}); - return true; - } - }, - dragfinish: function(inSender, inEvent) { - this.dragging = false; - inEvent.preventTap(); - this.doChange({value: this.value}); - return true; - }, - tap: function(inSender, inEvent) { - if (this.tappable) { - var v = this.calcKnobPosition(inEvent); - v = (this.increment) ? this.calcIncrement(v) : v; - this.tapped = true; - this.animateTo(v); - return true; - } - }, - down: function(inSender, inEvent) { - this.addClass("pressed"); - }, - leave: function(inSender, inEvent) { - this.removeClass("pressed"); - }, - //* @public - //* Animates to the given value. - animateTo: function(inValue) { - this.$.animator.play({ - startValue: this.value, - endValue: inValue, - node: this.hasNode() - }); - }, - //* @protected - animatorStep: function(inSender) { - this.setValue(inSender.value); - return true; - }, - animatorComplete: function(inSender) { - if (this.tapped) { - this.tapped = false; - this.doChange({value: this.value}); - } - this.doAnimateFinish(inSender); - return true; - } -}); diff --git a/lib/onyx/source/Spinner.js b/lib/onyx/source/Spinner.js deleted file mode 100644 index 9f31adf..0000000 --- a/lib/onyx/source/Spinner.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - A control that displays a spinner animation to indicate that activity is - taking place. By default, onyx.Spinner will display a light spinner, - suitable for displaying against a dark background. To render a dark spinner - to be shown on a lighter background, add the "onyx-light" class to the - spinner: - - {kind: "onyx.Spinner", classes: "onyx-light"} - - Typically, a spinner is shown to indicate activity and hidden to indicate - that the activity has ended. The spinner animation will automatically start - when a spinner is shown. If you wish, you may control the animation directly - by calling the *start*, *stop*, and *toggle* methods. -*/ -enyo.kind({ - name: "onyx.Spinner", - classes: "onyx-spinner", - //* @public - //* Stops the spinner animation. - stop: function() { - this.setShowing(false); - }, - //* Starts the spinner animation. - start: function() { - this.setShowing(true); - }, - //* Toggles the spinner animation on or off. - toggle: function() { - this.setShowing(!this.getShowing()); - } -}); diff --git a/lib/onyx/source/TabPanels.js b/lib/onyx/source/TabPanels.js deleted file mode 100644 index ae4d6da..0000000 --- a/lib/onyx/source/TabPanels.js +++ /dev/null @@ -1,128 +0,0 @@ -/** -enyo.TabPanels is a subkind of enyo.Panels that -displays a set of tabs, which allow navigation between the individual panels. -Unlike enyo.Panels, by default, the user cannot drag between the panels of a -TabPanels. This behavior can be enabled by setting *draggable* to true. - -Here's an example: - - enyo.kind({ - name: "App", - kind: "TabPanels", - fit: true, - components: [ - {kind: "MyStartPanel"}, - {kind: "MyMiddlePanel"}, - {kind: "MyLastPanel"} - ] - }); - new App().write(); -*/ -enyo.kind({ - name: "enyo.TabPanels", - kind: "Panels", - //* @protected - draggable: false, - tabTools: [ - {name: "scroller", kind: "Scroller", maxHeight: "100px", strategyKind: "TranslateScrollStrategy", thumb: false, vertical: "hidden", horizontal: "auto", components: [ - {name: "tabs", kind: "onyx.RadioGroup", style: "text-align: left; white-space: nowrap", controlClasses: "onyx-tabbutton", onActivate: "tabActivate"} - ]}, - {name: "client", fit: true, kind: "Panels", classes: "enyo-tab-panels", onTransitionStart: "clientTransitionStart"} - ], - create: function() { - this.inherited(arguments); - this.$.client.getPanels = enyo.bind(this, "getClientPanels"); - this.draggableChanged(); - this.animateChanged(); - this.wrapChanged(); - }, - initComponents: function() { - this.createChrome(this.tabTools); - this.inherited(arguments); - }, - getClientPanels: function() { - return this.getPanels(); - }, - flow: function() { - this.inherited(arguments); - this.$.client.flow(); - }, - reflow: function() { - this.inherited(arguments); - this.$.client.reflow(); - }, - draggableChanged: function() { - this.$.client.setDraggable(this.draggable); - this.draggable = false; - }, - animateChanged: function() { - this.$.client.setAnimate(this.animate); - this.animate = false; - }, - wrapChanged: function() { - this.$.client.setWrap(this.wrap); - this.wrap = false; - }, - isPanel: function(inControl) { - var n = inControl.name; - return !(n == "tabs" || n == "client" || n == "scroller"); - }, - addControl: function(inControl) { - this.inherited(arguments); - if (this.isPanel(inControl)) { - var c = inControl.caption || ("Tab " + this.$.tabs.controls.length); - var t = inControl._tab = this.$.tabs.createComponent({content: c}); - if (this.hasNode()) { - t.render(); - } - } - }, - removeControl: function(inControl) { - if (this.isPanel(inControl) && inControl._tab) { - inControl._tab.destroy(); - } - this.inherited(arguments); - }, - layoutKindChanged: function() { - if (!this.layout) { - this.layout = enyo.createFromKind("FittableRowsLayout", this); - } - this.$.client.setLayoutKind(this.layoutKind); - }, - indexChanged: function() { - // FIXME: initialization order problem - if (this.$.client.layout) { - this.$.client.setIndex(this.index); - } - this.index = this.$.client.getIndex(); - }, - tabActivate: function(inSender, inEvent) { - if (this.hasNode()) { - if (inEvent.originator.active) { - var i = inEvent.originator.indexInContainer(); - if (this.getIndex() != i) { - this.setIndex(i); - } - } - } - }, - clientTransitionStart: function(inSender, inEvent) { - var i = inEvent.toIndex; - var t = this.$.tabs.getClientControls()[i]; - if (t && t.hasNode()) { - this.$.tabs.setActive(t); - var tn = t.node; - var tl = tn.offsetLeft; - var tr = tl + tn.offsetWidth; - var sb = this.$.scroller.getScrollBounds(); - if (tr < sb.left || tr > sb.left + sb.clientWidth) { - this.$.scroller.scrollToControl(t); - } - } - return true; - }, - startTransition: enyo.nop, - finishTransition: enyo.nop, - stepTransition: enyo.nop, - refresh: enyo.nop -}); \ No newline at end of file diff --git a/lib/onyx/source/TextArea.js b/lib/onyx/source/TextArea.js deleted file mode 100644 index a15ac35..0000000 --- a/lib/onyx/source/TextArea.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - _onyx.TextArea_ is an Onyx-styled TextArea control, derived from - enyo.TextArea. Typically, an _onyx.TextArea_ - is placed inside an onyx.InputDecorator, - which provides styling, e.g.: - - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.TextArea", onchange: "inputChange"} - ]} - - For more information, see the documentation on - [Text Fields](https://github.com/enyojs/enyo/wiki/Text-Fields) in the Enyo - Developer Guide. -*/ -enyo.kind({ - name: "onyx.TextArea", - kind: "enyo.TextArea", - classes: "onyx-textarea" -}); diff --git a/lib/onyx/source/TimePicker.js b/lib/onyx/source/TimePicker.js deleted file mode 100644 index 1289412..0000000 --- a/lib/onyx/source/TimePicker.js +++ /dev/null @@ -1,210 +0,0 @@ -/** - _onyx.TimePicker_ is a group of onyx.Picker - controls displaying the current time. The user may change the hour, minute, - and AM/PM values. - - By default, _TimePicker_ tries to determine the current locale and use its - rules to format the time (including AM/PM). In order to do this - successfully, the _g11n_ library must be loaded; if it is not loaded, the - control defaults to using standard U.S. time format. - */ -enyo.kind({ - name: "onyx.TimePicker", - classes: "onyx-toolbar-inline", - published: { - //* If true, control is shown as disabled, and user can't select new values - disabled: false, - /** - Current locale used for formatting. Can be set after control - creation, in which case the control will be updated to reflect the - new value. - */ - locale: "en_us", - //* If true, 24-hour time is used. This is reset when locale is changed. - is24HrMode: null, - /** - The current Date object. When a Date object is passed to _setValue_, - the control is updated to reflect the new value. _getValue_ returns - a Date object. - */ - value: null - }, - events: { - /** - Fires when one of the TimePicker's fields is selected. - - _inEvent.name_ contains the name of the TimePicker that generated - the event. - - _inEvent.value_ contains the current Date value of the control. - */ - onSelect: "" - }, - create: function() { - this.inherited(arguments); - if (enyo.g11n) { - this.locale = enyo.g11n.currentLocale().getLocale(); - } - this.initDefaults(); - }, - initDefaults: function() { - // defaults that match en_US for when g11n isn't loaded - var am = "AM", pm = "PM"; - if (this.is24HrMode == null) { - this.is24HrMode = false; - } - // Attempt to use the g11n lib (ie assume it is loaded) - if (enyo.g11n) { - this._tf = new enyo.g11n.Fmts({locale:this.locale}); - am = this._tf.getAmCaption(); - pm = this._tf.getPmCaption(); - - if (this.is24HrMode == null) { - this.is24HrMode = !this._tf.isAmPm(); - } - } - - this.setupPickers(this._tf ? this._tf.getTimeFieldOrder() : 'hma'); - - var d = this.value = this.value || new Date(); - - // create hours - var i; - if (!this.is24HrMode){ - var h = d.getHours(); - h = (h === 0) ? 12 : h; - for (i=1; i<=12; i++) { - this.$.hourPicker.createComponent({content: i, value:i, active: (i == (h>12 ? h%12 : h))}); - } - } else { - for (i=0; i<24; i++) { - this.$.hourPicker.createComponent({content: i, value:i, active: (i == d.getHours())}); - } - } - - // create minutes - for (i=0; i<=59; i++) { - this.$.minutePicker.createComponent({content: (i < 10) ? ("0"+i):i, value:i, active: i == d.getMinutes()}); - } - - // create am/pm - if (d.getHours() >= 12) { - this.$.ampmPicker.createComponents([{content: am},{content:pm, active: true}]); - } - else { - this.$.ampmPicker.createComponents([{content: am, active: true},{content:pm}]); - } - this.$.ampmPicker.getParent().setShowing(!this.is24HrMode); - }, - setupPickers: function(ordering) { - var orderingArr = ordering.split(""); - var o,f,l; - for(f = 0, l = orderingArr.length; f < l; f++) { - o = orderingArr[f]; - switch (o){ - case 'h': this.createHour(); - break; - case 'm': this.createMinute(); - break; - case 'a': this.createAmPm(); - break; - default: break; - } - } - }, - createHour: function() { - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateHour", components: [ - {classes:"onyx-timepicker-hour", name: "hourPickerButton", disabled: this.disabled}, - {name: "hourPicker", kind: "onyx.Picker"} - ]} - ); - }, - createMinute: function() { - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateMinute", components: [ - {classes:"onyx-timepicker-minute", name: "minutePickerButton", disabled: this.disabled}, - {name: "minutePicker", kind: "onyx.Picker"} - ]} - ); - }, - createAmPm: function() { - this.createComponent( - {kind: "onyx.PickerDecorator", onSelect: "updateAmPm", components: [ - {classes:"onyx-timepicker-ampm", name: "ampmPickerButton", disabled: this.disabled}, - {name: "ampmPicker", kind: "onyx.Picker"} - ]} - ); - }, - disabledChanged: function() { - this.$.hourPickerButton.setDisabled(this.disabled); - this.$.minutePickerButton.setDisabled(this.disabled); - this.$.ampmPickerButton.setDisabled(this.disabled); - }, - localeChanged: function() { - //reset 24 hour mode when changing locales - this.is24HrMode = null; - this.refresh(); - }, - is24HrModeChanged: function() { - this.refresh(); - }, - valueChanged: function(){ - this.refresh(); - }, - updateHour: function(inSender, inEvent){ - var h = inEvent.selected.value; - if (!this.is24HrMode){ - var ampm = this.$.ampmPicker.getParent().controlAtIndex(0).content; - h = h + (h == 12 ? -12 : 0) + (this.isAm(ampm) ? 0 : 12); - } - this.value = this.calcTime(h, this.value.getMinutes()); - this.doSelect({name:this.name, value:this.value}); - return true; - }, - updateMinute: function(inSender, inEvent){ - this.value = this.calcTime(this.value.getHours(), inEvent.selected.value); - this.doSelect({name:this.name, value:this.value}); - return true; - }, - updateAmPm: function(inSender, inEvent){ - var h = this.value.getHours(); - if (!this.is24HrMode){ - h = h + (h > 11 ? (this.isAm(inEvent.content) ? -12 : 0) : (this.isAm(inEvent.content) ? 0 : 12)); - } - this.value = this.calcTime(h, this.value.getMinutes()); - this.doSelect({name:this.name, value:this.value}); - return true; - }, - calcTime: function(hour, minute){ - return new Date(this.value.getFullYear(), - this.value.getMonth(), - this.value.getDate(), - hour, minute, - this.value.getSeconds(), - this.value.getMilliseconds()); - }, - isAm: function(value){ - var am, pm, isAm; - //Workaround for pickers not having directly retrievable active item. Using it to find whether - //picker is on AM or PM (& have to check localized spelling as well) - try { - am = this._tf.getAmCaption(); - pm = this._tf.getPmCaption(); - } catch (err) { - am = "AM"; - pm = "PM"; - } - - if (value == am){ - return true; - } else { - return false; - } - }, - refresh: function(){ - this.destroyClientControls(); - this.initDefaults(); - this.render(); - } -}); diff --git a/lib/onyx/source/ToggleButton.js b/lib/onyx/source/ToggleButton.js deleted file mode 100644 index 8fffbcb..0000000 --- a/lib/onyx/source/ToggleButton.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - _onyx.ToggleButton_ is a control that looks like a switch with labels for - two states. Each time a ToggleButton is tapped, it switches its value and - fires an _onChange_ event. - - To get the value of the button, call _getValue_. - - For more information, see the documentation on - [Buttons](https://github.com/enyojs/enyo/wiki/Buttons) in the Enyo Developer - Guide. -*/ -enyo.kind({ - name: "onyx.ToggleButton", - classes: "onyx-toggle-button", - published: { - //* Used when the ToggleButton is part of a enyo.Group, true - //* to indicate that this is the active button of the group, false otherwise. - active: false, - //* Boolean indicating whether toggle button is currently in the "on" - //* state - value: false, - //* Label for toggle button's "on" state - onContent: "On", - //* Label for toggle button's "off" state - offContent: "Off", - //* If true, toggle button cannot be tapped and thus will not generate - //* any events - disabled: false - }, - events: { - /** - Fires when the user changes the value of the toggle button, but not - when the value is changed programmatically. - - _inEvent.value_ contains the value of the toggle button. - */ - onChange: "" - }, - //* @protected - handlers: { - ondragstart: "dragstart", - ondrag: "drag", - ondragfinish: "dragfinish" - }, - components: [ - {name: "contentOn", classes: "onyx-toggle-content on"}, - {name: "contentOff", classes: "onyx-toggle-content off"}, - {classes: "onyx-toggle-button-knob"} - ], - create: function() { - this.inherited(arguments); - this.value = Boolean(this.value || this.active); - this.onContentChanged(); - this.offContentChanged(); - this.disabledChanged(); - }, - rendered: function() { - this.inherited(arguments); - this.updateVisualState(); - }, - updateVisualState: function() { - this.addRemoveClass("off", !this.value); - this.$.contentOn.setShowing(this.value); - this.$.contentOff.setShowing(!this.value); - this.setActive(this.value); - }, - valueChanged: function() { - this.updateVisualState(); - this.doChange({value: this.value}); - }, - activeChanged: function() { - this.setValue(this.active); - this.bubble("onActivate"); - }, - onContentChanged: function() { - this.$.contentOn.setContent(this.onContent || ""); - this.$.contentOn.addRemoveClass("empty", !this.onContent); - }, - offContentChanged: function() { - this.$.contentOff.setContent(this.offContent || ""); - this.$.contentOff.addRemoveClass("empty", !this.onContent); - }, - disabledChanged: function() { - this.addRemoveClass("disabled", this.disabled); - }, - updateValue: function(inValue) { - if (!this.disabled) { - this.setValue(inValue); - } - }, - tap: function() { - this.updateValue(!this.value); - }, - dragstart: function(inSender, inEvent) { - if (inEvent.horizontal) { - inEvent.preventDefault(); - this.dragging = true; - this.dragged = false; - return true; - } - }, - drag: function(inSender, inEvent) { - if (this.dragging) { - var d = inEvent.dx; - if (Math.abs(d) > 10) { - this.updateValue(d > 0); - this.dragged = true; - } - return true; - } - }, - dragfinish: function(inSender, inEvent) { - this.dragging = false; - if (this.dragged) { - inEvent.preventTap(); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/source/ToggleIconButton.js b/lib/onyx/source/ToggleIconButton.js deleted file mode 100644 index df97438..0000000 --- a/lib/onyx/source/ToggleIconButton.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - _onyx.ToggleIconButton_ is an icon that acts like a toggle switch. The icon - image is specified by setting the _src_ property to a URL. - - {kind: "onyx.ToggleIconButton", src: "images/search.png", ontap: "buttonTap"} - - The image associated with the _src_ property is assumed to be a 32x64-pixel - strip, with the top half showing the button's normal state and the bottom - half showing its state when hovered-over or active. -*/ - -enyo.kind({ - name: "onyx.ToggleIconButton", - kind: "onyx.Icon", - published: { - /** - Used when the ToggleIconButton is part of an enyo.Group; set to true - to indicate that this is the active button in the group. - */ - active: false, - //* Boolean indicating whether the button is currently in the "on" state - value: false - }, - events: { - /** - Fires when the user changes the value of the toggle button, but not - when the value is changed programmatically. - */ - onChange: "" - }, - classes: "onyx-icon-button onyx-icon-toggle", - //* @protected - activeChanged: function() { - this.addRemoveClass("active", this.value); - this.bubble("onActivate"); - }, - updateValue: function(inValue) { - if (!this.disabled) { - this.setValue(inValue); - this.doChange({value: this.value}); - } - }, - tap: function() { - this.updateValue(!this.value); - }, - valueChanged: function() { - this.setActive(this.value); - }, - create: function() { - this.inherited(arguments); - this.value = Boolean(this.value || this.active); - }, - rendered: function() { - this.inherited(arguments); - this.valueChanged(); - this.removeClass('onyx-icon'); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/Toolbar.js b/lib/onyx/source/Toolbar.js deleted file mode 100644 index 09c06bb..0000000 --- a/lib/onyx/source/Toolbar.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - _onyx.Toolbar_ is a horizontal bar containing controls used to perform - common UI actions. - - A Toolbar customizes the styling of the controls it hosts, including - buttons, icons, and inputs. - - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.Button", content: "Favorites"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Enter a search term..."} - ]}, - {kind: "onyx.IconButton", src: "go.png"} - ]} - - For more information, see the documentation on - Toolbars in the - Enyo Developer Guide. -*/ -enyo.kind({ - name: "onyx.Toolbar", - classes: "onyx onyx-toolbar onyx-toolbar-inline", - create: function(){ - this.inherited(arguments); - - //workaround for android 4.0.3 rendering glitch (ENYO-674) - if (this.hasClass('onyx-menu-toolbar') && (enyo.platform.android >= 4)){ - this.applyStyle("position", "static"); - } - } -}); \ No newline at end of file diff --git a/lib/onyx/source/Tooltip.js b/lib/onyx/source/Tooltip.js deleted file mode 100644 index 6cf4b9a..0000000 --- a/lib/onyx/source/Tooltip.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - _onyx.Tooltip_ is a kind of onyx.Popup that works - with an onyx.TooltipDecorator. It - automatically displays a tooltip when the user hovers over the decorator. - The tooltip is positioned around the decorator where there is available - window space. - - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.Button", content: "Tooltip"}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} - ]} - - You may manually display the tooltip by calling its _show_ method. -*/ -enyo.kind({ - name: "onyx.Tooltip", - kind: "onyx.Popup", - classes: "onyx-tooltip below left-arrow", - //* If true, tooltip is automatically dismissed when user stops hovering - //* over the decorator - autoDismiss: false, - //* Hovering over the decorator for this length of time (in milliseconds) - //* causes the tooltip to appear. - showDelay: 500, - //* Default margin-left value - defaultLeft: -6, - //* @protected - handlers: { - onRequestShowTooltip: "requestShow", - onRequestHideTooltip: "requestHide" - }, - requestShow: function() { - this.showJob = setTimeout(enyo.bind(this, "show"), this.showDelay); - return true; - }, - cancelShow: function() { - clearTimeout(this.showJob); - }, - requestHide: function() { - this.cancelShow(); - return this.inherited(arguments); - }, - showingChanged: function() { - this.cancelShow(); - this.adjustPosition(true); - this.inherited(arguments); - }, - applyPosition: function(inRect) { - var s = ""; - for (var n in inRect) { - s += (n + ":" + inRect[n] + (isNaN(inRect[n]) ? "; " : "px; ")); - } - this.addStyles(s); - }, - adjustPosition: function(belowActivator) { - if (this.showing && this.hasNode()) { - var b = this.node.getBoundingClientRect(); - - //when the tooltip bottom goes below the window height move it above the decorator - if (b.top + b.height > window.innerHeight) { - this.addRemoveClass("below", false); - this.addRemoveClass("above", true); - } else { - this.addRemoveClass("above", false); - this.addRemoveClass("below", true); - } - - //when the tooltip's right edge is out of the window, align its right edge with the decorator left edge (approx) - if (b.left + b.width > window.innerWidth){ - this.applyPosition({'margin-left': -b.width, bottom: "auto"}); - //use the right-arrow - this.addRemoveClass("left-arrow", false); - this.addRemoveClass("right-arrow", true); - } - } - }, - resizeHandler: function() { - //reset the tooltip to align its left edge with the decorator - this.applyPosition({'margin-left': this.defaultLeft, bottom: "auto"}); - this.addRemoveClass("left-arrow", true); - this.addRemoveClass("right-arrow", false); - - this.adjustPosition(true); - this.inherited(arguments); - } -}); diff --git a/lib/onyx/source/TooltipDecorator.js b/lib/onyx/source/TooltipDecorator.js deleted file mode 100644 index 0bfe9a8..0000000 --- a/lib/onyx/source/TooltipDecorator.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - A control that activates an onyx.Tooltip. It - surrounds a control such as a button and displays the tooltip when the - control generates an _onEnter_ event: - - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.Button", content: "Tooltip"}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} - ]} - - Here's an example with an onyx.Input control and a - decorator around the input: - - {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Just an input..."} - ]}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for an input."} - ]} -*/ -enyo.kind({ - name: "onyx.TooltipDecorator", - defaultKind: "onyx.Button", - //* @protected - classes: "onyx-popup-decorator", - handlers: { - onenter: "enter", - onleave: "leave" - }, - enter: function() { - this.requestShowTooltip(); - }, - leave: function() { - this.requestHideTooltip(); - }, - tap: function() { - this.requestHideTooltip(); - }, - requestShowTooltip: function() { - this.waterfallDown("onRequestShowTooltip"); - }, - requestHideTooltip: function() { - this.waterfallDown("onRequestHideTooltip"); - } -}); \ No newline at end of file diff --git a/lib/onyx/source/design.js b/lib/onyx/source/design.js deleted file mode 100644 index 17e4c7d..0000000 --- a/lib/onyx/source/design.js +++ /dev/null @@ -1,168 +0,0 @@ -//* @protected -// Design description of the Onyx controls for use in the Ares designer tool. -Palette.model.push( - {name: "onyx", items: [ - {name: "onyx.Button", description: "A Pushbutton", - inline: {content: "onyx.Button", kind: "onyx.Button"}, - config: {content: "$name", isContainer: true, kind: "onyx.Button"} - }, - {name: "onyx.Checkbox", description: "A checkbox", - inline: {kind: "onyx.Checkbox"}, - config: {kind: "onyx.Checkbox"} - }, - {name: "onyx.DatePicker", description: "A control for choosing a date", - inline: {kind: "onyx.DatePicker"}, - config: {kind: "onyx.DatePicker"} - }, - {name: "onyx.Drawer", description: "A drawer that opens and closes", - inline: {kind: "onyx.Drawer"}, - config: {kind: "onyx.Drawer"} - }, - {name: "onyx.Groupbox", description: "A container for a group of controls", - inline: {kind: "onyx.Groupbox", components: [ - {content: "Header", kind: "onyx.GroupboxHeader"}, - {content: "Item", style: "padding: 10px;"} - ]}, - config: {kind: "onyx.Groupbox", isContainer: true, components: [ - {content: "Header", kind: "onyx.GroupboxHeader", isContainer: true}, - {content: "Item", style: "padding: 10px;"} - ]} - }, - {name: "onyx.GroupboxHeader", description: "A header for the Groupbox", - inline: {content: "Header", kind: "onyx.GroupboxHeader"}, - config: {content: "$name", kind: "onyx.GroupboxHeader", isContainer: true} - }, - {name: "onyx.Icon", description: "An Icon", - inline: {kind: "onyx.Icon"}, - config: {kind: "onyx.Icon"} - }, - {name: "onyx.IconButton", description: "An IconButton", - inline: {kind: "onyx.IconButton"}, - config: {kind: "onyx.IconButton"} - }, - {name: "onyx.InputDecorator", description: "Style an Input", - inline: {kind: "onyx.InputDecorator", components: [ - {kind: "Input", placeholder: "Enter text here"} - ]}, - config: {kind: "onyx.InputDecorator", components: [ - {kind: "Input", placeholder: "Enter text here"} - ]} - }, - {name: "onyx.Input", description: "Text input control", - inline: {value: "onyx.Input", kind: "onyx.Input"}, - config: {kind: "onyx.Input"} - }, - {name: "onyx.Item", description: "Stackable item, for lists and menus", - inline: {value: "onyx.Item", kind: "onyx.Item"}, - config: {content: "$name", kind: "onyx.Item"} - }, - {name: "onyx.MenuDecorator", description: "A Menu and activating control", - inline: {}, - config: {kind: "onyx.MenuDecorator", components: [ - {content: "Show menu"}, - {kind: "onyx.Menu", components: [ - {content: "1"}, - {content: "2"}, - {classes: "onyx-menu-divider"}, - {content: "Label", classes: "onyx-menu-label"}, - {content: "3"} - ]} - ]} - }, - {name: "onyx.PickerDecorator", description: "A Picker and activating control", - inline: {}, - config: {kind: "onyx.PickerDecorator", components: [ - {content: "Pick1"}, //this uses the defaultKind property of PickerDecorator to inherit from PickerButton - {kind: "onyx.Picker", components: [ - {content: "Pick1", active: true}, - {content: "Pick2"}, - {content: "Pick3"}, - {content: "Pick4"} - ]} - ]} - }, - {name: "onyx.ProgressBar", description: "A progress bar", - inline: {}, - config: {kind: "onyx.ProgressBar"} - }, - {name: "onyx.ProgressButton", description: "A progress button", - inline: {}, - config: {kind: "onyx.ProgressButton"} - }, - {name: "onyx.RadioGroup", description: "Only one control in a group can be 'active' at a time", - inline: {kind: "onyx.RadioGroup", components: [ - {content: "A"}, - {content: "B"}, - {content: "C"} - ]}, - config: {kind: "onyx.RadioGroup", isContainer: true, components: [ - {content: "RadioButton"} - ]} - }, - {name: "onyx.RadioButton", description: "An on-off button, for use with RadioGroup", - inline: {content: "RadioButton", kind: "onyx.RadioButton"}, - config: {content: "$name", kind: "onyx.RadioButton"} - }, - {name: "onyx.RangeSlider", description: "A Slider with two knobs", - inline: {value: "onyx.RangeSlider", kind: "onyx.RangeSlider"}, - config: {kind: "onyx.RangeSlider"} - }, - {name: "onyx.RichText", description: "A Rich text input", - inline: {value: "onyx.RichText", kind: "onyx.RichText"}, - config: {kind: "onyx.RichText", style: "height: 100px"} - }, - {name: "onyx.Slider", description: "A Slider", - inline: {value: "onyx.Slider", kind: "onyx.Slider"}, - config: {kind: "onyx.Slider"} - }, - {name: "onyx.Spinner", description: "A Spinner", - inline: {kind: "onyx.Spinner"}, - config: {kind: "onyx.Spinner", classes: "onyx-light"} - }, - {name: "onyx.TextArea", description: "A multi-line text input", - inline: {kind: "onyx.TextArea"}, - config: {kind: "onyx.TextArea"} - }, - {name: "onyx.TimePicker", description: "A Picker for time", - inline: {kind: "onyx.TimePicker"}, - config: {kind: "onyx.TimePicker"} - }, - {name: "onyx.ToggleButton", description: "A pushbutton that toggles between active and inactive states", - inline: {kind: "onyx.ToggleButton"}, - config: {kind: "onyx.ToggleButton"} - }, - {name: "onyx.ToggleIconButton", description: "A ToggleButton that toggles between active and inactive images", - inline: {kind: "onyx.ToggleIconButton"}, - config: {kind: "onyx.ToggleIconButton"} - }, - {name: "onyx.Toolbar", description: "A toolbar", - inline: {kind: "onyx.Toolbar"}, - config: {isContainer: true, kind: "onyx.Toolbar"} - }, - {name: "onyx.MoreToolbar", description: "A toolbar which adapts to screen width ", - inline: {kind: "onyx.Toolbar"}, - config: {isContainer: true, kind: "onyx.MoreToolbar", components: [ - {content: "MoreToolbar"}, - {kind: "onyx.Item", content: "Resize Me!"}, - {kind: "onyx.Button", content: "this"}, - {kind: "onyx.Button", content: "toolbar"}, - {kind: "onyx.Button", content: "has"}, - {kind: "onyx.Button", content: "many"}, - {kind: "onyx.Button", content: "items"}, - {kind: "onyx.Button", content: "in"}, - {kind: "onyx.Button", content: "it"} - ]} - }, - {name: "onyx.Grabber", description: "Graphical 'handle' for dragging", - inline: {kind: "onyx.Grabber", style: "background-color: #333; padding: 4px 12px;"}, - config: {kind: "onyx.Grabber"} - }, - {name: "onyx.TooltipDecorator", description: "Combines a conrol (typically a button) and a tooltip describing it", - inline: {kind: "onyx.Tooltip"}, - config: {kind: "onyx.TooltipDecorator", components: [ - {kind: "onyx.Button", content: "Hover for tooltip"}, - {kind: "onyx.Tooltip", content: "I'm a tooltip for a button."} - ]} - } - ]} -); diff --git a/lib/onyx/source/package.js b/lib/onyx/source/package.js deleted file mode 100644 index a5f763e..0000000 --- a/lib/onyx/source/package.js +++ /dev/null @@ -1,42 +0,0 @@ -enyo.depends( - "Icon.js", - "Button.js", - "IconButton.js", - "Checkbox.js", - "Drawer.js", - "Grabber.js", - "Groupbox.js", - "Input.js", - "Popup.js", - "TextArea.js", - "RichText.js", - "InputDecorator.js", - "Tooltip.js", - "TooltipDecorator.js", - "MenuDecorator.js", - "Menu.js", - "MenuItem.js", - "PickerDecorator.js", - "PickerButton.js", - "Picker.js", - "FlyweightPicker.js", - "DatePicker.js", - "TimePicker.js", - "RadioButton.js", - "RadioGroup.js", - "ToggleButton.js", - "ToggleIconButton.js", - "Toolbar.js", - "Tooltip.js", - "TooltipDecorator.js", - "ProgressBar.js", - "ProgressButton.js", - "Scrim.js", - "Slider.js", - "RangeSlider.js", - "Item.js", - "Spinner.js", - "MoreToolbar.js", - "IntegerPicker.js", - "ContextualPopup.js" -); \ No newline at end of file diff --git a/lib/onyx/source/wip-package.js b/lib/onyx/source/wip-package.js deleted file mode 100644 index a00be44..0000000 --- a/lib/onyx/source/wip-package.js +++ /dev/null @@ -1,3 +0,0 @@ -enyo.depends( - "TabPanels.js" -); \ No newline at end of file diff --git a/package.js b/package.js index ac5ed78..2a0b582 100644 --- a/package.js +++ b/package.js @@ -1,5 +1,6 @@ -/* - == DO NOT EDIT THIS FILE! == - This is necessary to keep paths correct for the minification process -*/ -enyo.depends("source"); +enyo.depends( + "$lib/layout", + "$lib/onyx", + "source/App.css", + "source/App.js" +); diff --git a/source/Scheduler.css b/source/Scheduler.css deleted file mode 100644 index ca84d09..0000000 --- a/source/Scheduler.css +++ /dev/null @@ -1,94 +0,0 @@ -/* - Put anything you reference with "url()" in ../assets/ - This way, you can minify your application, and just remove the "source" folder for production -*/ - -#upper_toolbar{ - text-align: center; -} - -#bottom_toolbar{ - height: 70px; -} - - -.nice-padding { - padding: 3px; -} - -.button_image{ - height: 40px; - width: 40px; -} - -.onyx-sample-tools > * { - margin: 3px; -} - -.button{ - height: 50px; - width: 50px; - margin: 0px 10px 0px 10px; - border: 0 0 0 0; - padding: 0 0 0 0; -} - -.onyx-sample { - padding: 10px; -} -.onyx-sample-tools { - padding-bottom:10px; -} - -.onyx-sample-divider { - color: #F49200; - text-transform: uppercase; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; - font-weight: bold; - margin-bottom: 8px; -} -.onyx-sample-result-box { - width:100%; -} -.onyx-sample-result { - padding:8px; -} -.onyx-sample-spaced-button { - margin:3px; -} -.onyx-sample-animate-label { - vertical-align:middle; - padding-left:5px; - margin-right: 15px; -} -.onyx-sample-label { - color: #1879CD; - font-size: 18px; - text-transform: uppercase; -} -.onyx-sample-popup { - font-size: 30px; - text-align: center; -} -.onyx-contextualpopup-button-container{ - padding:10px; -} - -.onyx-sample-tools.group{ - position: relative; - left: 50%; - margin-left: -105px; -} - -.Input{ - text-align: center; -} - -.onyx-sample-result{ - text-align: center; -} - -.result_header{ - text-align: center; -} \ No newline at end of file diff --git a/source/Scheduler.js b/source/Scheduler.js deleted file mode 100644 index 8986875..0000000 --- a/source/Scheduler.js +++ /dev/null @@ -1,55 +0,0 @@ -enyo.kind({ - name: "Scheduler", - kind: "FittableRows", - fit: true, - published:{ - init : 0 - }, - components:[ - //toobar showing the tapped function - {kind: "onyx.Toolbar", name: "scheduler_toolbar", id: "upper_toolbar", content: "To do Lists"}, - {kind: "enyo.Scroller", fit: true, components: [ - {name: "main", classes: "nice-padding", allowHtml: true} - ]}, - // bottom toolbar and buttons - {kind: "onyx.Toolbar", id: "bottom_toolbar", components: [ - //buttons - {kind: "Group", onActivate:"buttonActivated", classes: "onyx-sample-tools group", defaultKind: "onyx.Button", highlander: true, - components: [ - {components:[{kind:"Image", classes:"button_image" ,src: "assets/check.png"}] , id: "To do Lists", active: true, classes: "button"}, - {components:[{kind:"Image", classes:"button_image" ,src: "assets/week.png"}] , id: "Weekly Schedule", classes: "button"}, - {components:[{kind:"Image", classes:"button_image" ,src: "assets/month.png"}] , id: "Calendar", classes: "button"}]}, - ]}, - ], - - buttonActivated: function(inSender, inEvent) { - // render only when it is started - if (this.init == 0){ - this.$.main.createComponent({kind:"To_do", name: "To_do"}); - this.$.main.createComponent({kind:"weekly", name: "weekly"}); - this.$.main.createComponent({kind: "calendar", name:"calendar"}); - this.$.main.render(); - this.init++; - } - // when each button is tapped show the tapped component and hide the others - if (inEvent.originator.getActive()) { - this.$.scheduler_toolbar.setContent(inEvent.originator.getId()); - if(inEvent.originator.getId() == "To do Lists"){ - this.$.main.$.weekly.hide(); - this.$.main.$.calendar.hide(); - this.$.main.$.To_do.show(); - } - else if(inEvent.originator.getId() == "Weekly Schedule"){ - this.$.main.$.To_do.hide(); - this.$.main.$.calendar.hide(); - this.$.main.$.weekly.show(); - } - else{ - this.$.main.$.To_do.hide(); - this.$.main.$.weekly.hide(); - this.$.main.$.calendar.show(); - } - } - } - -}); diff --git a/source/Theme.less b/source/Theme.less deleted file mode 100644 index b9b13c8..0000000 --- a/source/Theme.less +++ /dev/null @@ -1,26 +0,0 @@ -/* - You can modify the Onyx theme by adding variable and rule overrides to this - file. To enable theming, follow these steps: - - 1. In debug.html, uncomment the line referencing "less-.min.js". - 2. In package.js, change "$lib/onyx" to "$lib/onyx/source". - 3. Also in package.js, add "Theme.less" (this file). - 4. Add variable and rule overrides below. - - See [https://github.com/enyojs/enyo/wiki/UI-Theming] for more information. -*/ - - -/* Onyx default variable definitions: */ -@import "../lib/onyx/css/onyx-variables.less"; - -/* Place your Onyx variable overrides here -------------------- */ - -/* ------------------------------------- end variable overrides */ - -/* Onyx rule definitions: */ -@import "../lib/onyx/css/onyx-rules.less"; - -/* Place your Onyx rule overrides here ------------------------ */ - -/* ----------------------------------------- end rule overrides */ diff --git a/source/function/calendar.css b/source/function/calendar.css deleted file mode 100644 index a44fbaa..0000000 --- a/source/function/calendar.css +++ /dev/null @@ -1,73 +0,0 @@ -.calendar { - padding: 0 20px; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; -} -.calendar table { - width: 100%; - height: 90%; - border-collapse: collapse; -} -.calendar .header td { - padding: 5px 2px; - width: 14%; - height: 16px; - font-weight: bold; - text-transform: uppercase; - text-align: center; -} -.calendar .header td:first-of-type { - color: red; -} - -.calendar .header td:last-of-type { - color: blue; -} - -.calendar td { - padding: 2px; - vertical-align: top; - border: 1px solid #999; - background-color: #FFF; -} -.calendar td.current { - background-color: #226B9A; - color: #FFF; - font-weight: bold; -} -.calendar .section { - padding-top: 20px; - font-size: 20px; - display: block; - color: #000000; - text-transform: uppercase; - font-weight: bold; - margin-bottom: 8px; - text-align: center; -} -.calendar .results { - margin: 20px 0; - padding: 20px; - min-height: 24px; - border-radius: 10px; - color: #FFF; - background-color: #555; -} - -.prev_button{ - float: left; -} - -.next_button{ - float: right; -} - -.contentSection{ - display: inline; -} - -.Typing{ - width: 115px; - height: 25px; - text-align: center; -} \ No newline at end of file diff --git a/source/function/calendar.js b/source/function/calendar.js deleted file mode 100644 index 3c5d33d..0000000 --- a/source/function/calendar.js +++ /dev/null @@ -1,416 +0,0 @@ -enyo.kind({ - name: "calendar", - classes: "calendar enyo-fit", - published:{ - "setYear":"", - "setMonth":"" - }, - components: [ - {name: "month", classes: "section", allowHtml: true, components:[ - {kind: "onyx.IconButton", src: "assets/left_arrow.png", ontap:"leftTapped", classes:"prev_button"}, - {name: "innerMonth", classes: "contentSection", ontap:"calendarTapped", popup:"popupInput"}, - {name: "popupInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components:[ - {classes:"inputContainer", components:[ - {name: "yearInput", kind: "onyx.Input", placeholder: "Type Year here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, - {content: "년", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, - {name: "monthInput", kind: "onyx.Input", placeholder: "Type Month here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, - {content: "월", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, - ]}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, - {kind: "onyx.Button", content: "Apply", ontap: "applyYearMonth", classes: "popupButton", popup: "showMessage"}, - {name: "showMessage", kind: "onyx.Popup",onkeypress:"closeMessagePopup2", centered: true, modal: true, floating: true, components:[ - {name:"popupContents", content:"", allowHtml: true}, - {tag: "br"}, - {kind:"onyx.Button", content: "Close", ontap: "closeMessagePopup", style:"position:relative; left: 50%; margin-left: -39.5px"} - ]} - ]}, - {kind: "onyx.IconButton", src: "assets/right_arrow.png", ontap:"rightTapped", classes:"next_button"} - ]}, - {name:"monthTable", kind: "enyo.Table", components: [ - {classes: "header", components: [ - {content: "Sun"}, - {content: "Mon"}, - {content: "Tue"}, - {content: "Wed"}, - {content: "Thu"}, - {content: "Fri"}, - {content: "Sat"} - ]} - ]} - ], - create: function() { - if(!localStorage.count_c){ - localStorage.setItem('count_c', '0'); - } - this.inherited(arguments); - - var currentRow, - dateObj = new Date(); - - // calculate current date - var currentDate = dateObj.getDate(); - - // calculate date of first day of the month - dateObj.setDate(1); - var offset = dateObj.getDay(); - - // calculate date of last day of the month - this.setYear = dateObj.getFullYear(); - this.setMonth = dateObj.getMonth(); - var lastDate = this.getDaysInMonth(dateObj.getMonth(), dateObj.getFullYear()); - - // this calculation can probably be simplified, but allows for padding blank spaces in - // the calendar to display a "full" table - for (var i=0; i=lastDate+offset) { - currentRow.createComponent({}); - } else { - var cellDay = new functionCell(); - cellDay.number = (i-offset+1); - cellDay.year = this.setYear; - cellDay.month = this.setMonth; - if ((i-offset+1) === currentDate) { - cellDay.active = true; - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - } - - // set month display - this.$.innerMonth.setContent(dateObj.getFullYear() + "년 " + (dateObj.getMonth()+1) +"월"); - }, - // adapted from http://stackoverflow.com/questions/1810984/number-of-days-in-any-month - getDaysInMonth: function(m, y) { - return (/8|3|5|10/).test(m)?30:m==1?((y%4===0)&&y%100)||(y%400===0)?29:28:31; - }, - - leftTapped: function(inSender, inEvent){ - this.$.monthTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - if(this.setMonth > 0){ - this.setMonth -= 1; - } - else{ - this.setMonth = 11; - this.setYear -= 1; - } - var dateObj2 = new Date(this.setYear, this.setMonth, 1); - var currentDate = dateObj.getDate(); - var offset = dateObj2.getDay(); - var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); - // this calculation can probably be simplified, but allows for padding blank spaces in - // the calendar to display a "full" table - for (var i=0; i=lastDate+offset) { - currentRow.createComponent({}); - } else { - var cellDay = new functionCell(); - cellDay.number = (i-offset+1); - cellDay.year = this.setYear; - cellDay.month = this.setMonth; - if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { - cellDay.active = true; - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - } - - // set month display - this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); - this.$.monthTable.render(); - }, - - rightTapped: function(inSender,inEvent){ - this.$.monthTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - if(this.setMonth < 11){ - this.setMonth += 1; - } - else{ - this.setMonth = 0; - this.setYear += 1; - } - var dateObj2 = new Date(this.setYear, this.setMonth, 1); - var currentDate = dateObj.getDate(); - var offset = dateObj2.getDay(); - var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); - // this calculation can probably be simplified, but allows for padding blank spaces in - // the calendar to display a "full" table - for (var i=0; i=lastDate+offset) { - currentRow.createComponent({}); - } else { - var cellDay = new functionCell(); - cellDay.number = (i-offset+1); - cellDay.year = this.setYear; - cellDay.month = this.setMonth; - if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { - cellDay.active = true; - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - } - - // set month display - this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); - this.$.monthTable.render(); - }, - - calendarTapped: function(inSender, inEvent){ - this.$.popupInput.show(); - }, - - closePopup: function(inSender, inEvent){ - this.$.popupInput.hide(); - }, - - popupShown: function() { - this.$.yearInput.focus(); - }, - - enterDetected: function(inSender, inEvent){ - if(inEvent.keyCode == 13){ - this.applyYearMonth(); - } - }, - - applyYearMonth: function(inSender, inEvent){ - var yearInputValue = parseFloat(this.$.yearInput.getValue()); - var monthInputValue = parseFloat(this.$.monthInput.getValue() - 1); - if(this.$.yearInput.getValue() == ""){ - this.$.popupContents.setContent("please input Year value!"); - this.$.showMessage.show(); - return; - } - if(this.$.monthInput.getValue() == ""){ - this.$.popupContents.setContent("please input Month value!"); - this.$.showMessage.show(); - return; - } - if(this.isInt(yearInputValue) == false){ - this.$.popupContents.setContent("Invalid Year value!
    please input integer value"); - this.$.showMessage.show(); - return; - } - else if(yearInputValue < 1000 || yearInputValue > 3000){ - this.$.popupContents.setContent("Invalid Year value!
    please input value between 1000 ~ 3000"); - this.$.showMessage.show(); - return; - } - this.setYear = yearInputValue; - if(this.isInt(monthInputValue) == false){ - this.$.popupContents.setContent("Invalid Month value!
    please input integer value"); - this.$.showMessage.show(); - return; - } - else if(monthInputValue < 0 || monthInputValue > 11){ - this.$.popupContents.setContent("Invalid Month value!
    please input value between 1 ~ 12"); - this.$.showMessage.show(); - return; - } - this.setMonth = monthInputValue; - this.$.popupInput.hide(); - this.$.monthTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - this.$.yearInput.clear(); - this.$.monthInput.clear(); - - var dateObj2 = new Date(this.setYear, this.setMonth, 1); - var currentDate = dateObj.getDate(); - var offset = dateObj2.getDay(); - var lastDate = this.getDaysInMonth(this.setMonth, this.setYear); - // this calculation can probably be simplified, but allows for padding blank spaces in - // the calendar to display a "full" table - for (var i=0; i=lastDate+offset) { - currentRow.createComponent({}); - } else { - var cellDay = new functionCell(); - cellDay.number = (i-offset+1); - cellDay.year = this.setYear; - cellDay.month = this.setMonth; - if ((i-offset+1) === currentDate && dateObj.getFullYear() == this.setYear && dateObj.getMonth() == this.setMonth) { - cellDay.active = true; - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - } - - // set month display - this.$.innerMonth.setContent(this.setYear + "년 " + (this.setMonth+1) +"월"); - this.$.monthTable.render(); - }, - - closeMessagePopup: function(inSender, inEvent){ - this.$.showMessage.hide(); - }, - - closeMessagePopup2: function(inSender,inEvent){ - if(inEvent.keyCode == 13){ - this.closeMessagePopup(); - } - }, - - isInt: function(value){ - return typeof(value) === 'number' && value % 1 == 0; - }, - - ontapTest: function(inSender, inEvent){ - alert('this is a ' + inSender.getContent()); - - }, -}); - -enyo.kind({ - name:"functionCell", - kind:"enyo.TableCell", - components:[ - {name: "cellContent", popup:"scheduleInput", popup:"scheduleShow", content:""}, - {name:"scheduleInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "", components:[ - {content: "제목", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, - {name: "subjectInput", kind: "onyx.Input", placeholder: "Type subject here", classes:"Typing", style: "margin: 10px", onkeypress:""}, - {tag:"br"}, - {content: "시간", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, - {name: "timeInput", kind: "onyx.Input", placeholder: "Type Time(00:00) here", classes:"Typing", style: "margin: 10px", onkeypress:""}, - {tag:"br"}, - {content: "장소", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, - {name: "placeInput", kind: "onyx.Input", placeholder: "Type Place here", classes:"Typing", style: "margin: 10px", onkeypress:""}, - {tag:"br"}, - {tag:"br"}, - {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, - {kind: "onyx.Button", content: "Apply", ontap: "applySchedule", classes: "popupButton"} - ]}, - {name:"scheduleShow", kind:"onyx.Popup", onHide:"ScheduleListHide", modal: true, floating: true, components:[ - {kind: "onyx.Groupbox", components: [ - {name:"scheduleList", kind: "onyx.GroupboxHeader", content: "Schedule List"} - ]} - ]}, - {name: "scheduleImage", kind:"enyo.Image", src:"assets/dot.png", active: false, style:"position: relative; left: 95%; height: 10px; width: 10px;"}, - {name: "schedule", components:[ - {name:"subject", content:""}, - {name:"time", content:""}, - {name:"place", content:""} - ]} - ], - published:{ - active: false, - isSchedule: false, - number: "", - year: "", - month: "", - }, - handlers:{ - ontap:"cellTap", - onleave: "cellDeactive" - }, - create: function(){ - this.inherited(arguments); - this.$.cellContent.setContent(this.number); - - for(var i = 1 ; i < parseInt(localStorage.count_c)+1 ; i++){ - if((localStorage.getItem(i.toString()+'c')) != null){ - var Obj = {}; - Obj = JSON.parse(localStorage.getItem(i.toString()+'c')); - if(Obj.year == this.year && Obj.month == this.month && Obj.date == this.number){ - this.restoreSchedule(Obj.subject, Obj.time, Obj.place); - } - } - } - - this.$.schedule.hide(); - if(this.isSchedule == false){ - this.$.scheduleImage.hide(); - } - }, - restoreSchedule: function(subject, time, place){ - var newSchedule = new scheduleThing(); - newSchedule.setContent(time + "에 " + place + "에서 " + subject +"이(가) 있습니다."); - this.$.scheduleList.createComponent(newSchedule); - this.$.scheduleList.render(); - this.isSchedule = true; - this.$.scheduleImage.show(); - }, - cellTap: function(inSender, inEvent){ - if(this.active == false){ - this.active = true; - this.applyStyle("background-color","yellow"); - if(this.isSchedule == true){ - this.$.scheduleShow.showAtEvent(inEvent); - } - } - else if(this.active == true){ - this.$.scheduleInput.show(); - } - }, - cellDeactive: function(inSender, inEvent){ - if(this.active == true){ - this.active = false; - this.applyStyle("background-color", "white"); - if(this.getClassAttribute() == "current"){ - this.applyStyle("background-color", "#226B9A"); - } - } - }, - closePopup: function(inSender, inEvent){ - this.$.scheduleInput.hide(); - }, - - applySchedule: function(inSender, inEvent){ - var subject = this.$.subjectInput.getValue(); - var time = this.$.timeInput.getValue(); - var place = this.$.placeInput.getValue(); - this.$.subjectInput.clear(); - this.$.timeInput.clear(); - this.$.placeInput.clear(); - - var newSchedule = new scheduleThing(); - newSchedule.setContent(time + "에 " + place + "에서 " + subject +"이(가) 있습니다."); - var count_c = parseInt(localStorage.count_c); - count_c++; - localStorage.setItem('count_c', count_c); - var Obj_c = []; - Obj_c[count_c] = {year: this.year, month: this.month, date: this.number, subject: subject, time: time, place: place }; - localStorage.setItem(count_c.toString() + 'c', JSON.stringify(Obj_c[count_c])); - this.$.scheduleList.createComponent(newSchedule); - this.$.scheduleList.render(); - this.isSchedule = true; - this.$.scheduleImage.show(); - this.$.scheduleInput.hide(); - }, - - ScheduleListHide: function(inSender, inEvent){ - if(this.active == false){ - this.active = true; - this.applyStyle("background-color","yellow"); - } - } -}); - -enyo.kind({ - name: "scheduleThing", - content: "", - handlers:{ - ontap: "editSchedule" - } -}); \ No newline at end of file diff --git a/source/function/package.js b/source/function/package.js deleted file mode 100644 index 68a4c90..0000000 --- a/source/function/package.js +++ /dev/null @@ -1,8 +0,0 @@ -enyo.depends( - "to_do.js", - "weekly.js", - "calendar.js", - "to_do.css", - "calendar.css", - "weekly.css" -); \ No newline at end of file diff --git a/source/function/to_do.css b/source/function/to_do.css deleted file mode 100644 index e492dd1..0000000 --- a/source/function/to_do.css +++ /dev/null @@ -1,16 +0,0 @@ - -.del_button{ - float: right; - height: 32px; - width: 32px; -} - -.ThingsCheckbox{ - float: left; - left: 5px; - vertical-align: middle; -} - -.ThingsCss{ - height: 35px; -} diff --git a/source/function/to_do.js b/source/function/to_do.js deleted file mode 100644 index d69b034..0000000 --- a/source/function/to_do.js +++ /dev/null @@ -1,114 +0,0 @@ -enyo.kind({ - name: "To_do", - components:[ - {kind: "onyx.InputDecorator", style: "width: 100%;", components: [ - {kind: "onyx.Input", name:"to_do_input", classes: "Input", style: "width: 100%;", placeholder: "What do you need to do?", onkeypress:"inputChanged"} - ]}, - {tag: "br"}, - {kind: "onyx.Groupbox", classes:"onyx-sample-result-box", components: [ - {kind: "onyx.GroupboxHeader", classes: "result_header", content: "To do Lists"}, - {name:"result_2", classes:"onyx-sample-result", content:"There is not things to do"} - ]} - ], - //by enter key, create new component - inputChanged: function(inSender, inEvent) { - if(inEvent.keyCode == 13){ - var count = parseInt(localStorage.count); - var Obj =[]; - count++; - localStorage.setItem('count', count); - Obj[count] = {number : count, state : 1, value : inSender.getValue()}; - localStorage.setItem(count, JSON.stringify(Obj[count])); - this.$.result_2.createComponent({kind:"Things", Things_content: inSender.getValue(), id: count}); - this.$.result_2.render(); - this.$.to_do_input.clear(); - } - }, - changeFocus: function(inSender, inEvent) { - enyo.forEach([this.$.inputDecorator, this.$.inputDecorator2, this.$.inputDecorator3], function(inItem) { - inItem.setAlwaysLooksFocused(inSender.getValue()); - // If disabling alwaysLooksFocused, we need to blur the - // InputDecorator for the setting to go into effect - if (!inSender.getValue()) { - inItem.triggerHandler("onblur"); - } - }); - }, - - create: function(){ - //localStorage.clear(); - this.inherited(arguments); - if(!localStorage.count){ - localStorage.setItem('count','0'); - } - else{ - for(var i = 1; i < parseInt(localStorage.count)+1 ; i++){ - if(localStorage.getItem(i) != null){ - var Obj = {}; - Obj = JSON.parse(localStorage.getItem(i)); - this.$.result_2.createComponent({kind:"Things", Things_content: Obj.value, state: Obj.state, id: i }); - } - } - this.$.result_2.render(); - } - - } - -}); - - -enyo.kind({ - name: "Things", - classes: "ThingsCss", - kind: "onyx.Toolbar", - published:{ - "Things_content":"", - "state": 1 - }, - components:[ - {name: "ThingsCheck", kind:"onyx.Checkbox", onchange:"checkboxChanged", classes:"ThingsCheckbox"}, - {name: "ThingsName", content:"", classes: "ThingsContent"}, - {kind: "onyx.IconButton", src: "assets/delete_button.png", ontap:"iconTapped", classes:"del_button"} - ], - create: function(){ - this.inherited(arguments); - if(this.state != 1){ - this.$.ThingsCheck.active = true; - } - if(this.Things_content){ - this.Things_contentChanged(); - } - }, - Things_contentChanged: function(){ - this.$.ThingsName.setContent(this.Things_content); - if(this.$.ThingsCheck.active == true){ - this.$.ThingsName.applyStyle("text-decoration","line-through"); - } - }, - checkboxChanged: function(inSender, inEvent) { - if(inSender.getValue()){ - this.$.ThingsName.applyStyle("text-decoration","line-through"); - var Obj = {} - Obj = JSON.parse(localStorage.getItem(this.id)); - Obj.state = 0; - localStorage.setItem(this.id, JSON.stringify(Obj)); - } - else{ - this.$.ThingsName.applyStyle("text-decoration","none"); - var Obj = {}; - Obj = JSON.parse(localStorage.getItem(this.id)); - Obj.state = 1; - localStorage.setItem(this.id, JSON.stringify(Obj)); - } - }, - iconTapped: function(inSender, inEvent){ - var parent = this.parent; - this.destroy(); - parent.render(); - }, - - destroy: function(){ - localStorage.removeItem(this.id); - this.inherited(arguments); - } -}); \ No newline at end of file diff --git a/source/function/weekly.css b/source/function/weekly.css deleted file mode 100644 index 493a1d5..0000000 --- a/source/function/weekly.css +++ /dev/null @@ -1,93 +0,0 @@ -.weekly { - padding: 0 20px; - font-family: Segoe UI, Prelude Medium, Helvetica, Verdana, sans-serif; - font-size: 14px; -} -.weekly table { - width: 100%; - height: 90%; - border-collapse: collapse; -} -.weekly td.header { - padding: 5px 2px; - width: 14%; - height: 16px; - font-weight: bold; - text-transform: uppercase; - text-align: center; -} -.weekly td:first-of-type.header { - color: red; -} - -.weekly td:last-of-type.header { - color: blue; -} - -.weekly td { - padding: 2px; - vertical-align: top; - border: 1px solid #999; - background-color: #FFF; -} -.weekly td.current { - background-color: #226B9A; - color: #FFF; - padding: 5px 2px; - width: 14%; - height: 16px; - font-weight: bold; - text-transform: uppercase; - text-align: center; -} - -.weekly td.currentTime { - background-color: #226B9A; - color: #FFF; -} - - -.weekly .section { - padding-top: 20px; - font-size: 20px; - color: #000000; - display: block; - text-transform: uppercase; - font-weight: bold; - margin-bottom: 8px; - text-align: center; -} -.weekly .results { - margin: 20px 0; - padding: 20px; - min-height: 24px; - border-radius: 10px; - color: #FFF; - background-color: #555; -} - -.weekly .prev_button{ - float: left; -} - -.weekly .next_button{ - float: right; -} - -.contentSection{ - display: inline; -} - -.popupButton{ - float: right; -} - -.Typing{ - width: 115px; - height: 25px; - text-align: center; -} - -.inputContainer{ - display: inline-flex; -} \ No newline at end of file diff --git a/source/function/weekly.js b/source/function/weekly.js deleted file mode 100644 index 08aa626..0000000 --- a/source/function/weekly.js +++ /dev/null @@ -1,526 +0,0 @@ -enyo.kind({ - name: "weekly", - classes: "weekly enyo-fit", - components: [ - {name: "week", classes: "section", components:[ - {kind: "onyx.IconButton", src: "assets/left_arrow.png", ontap:"leftTapped", classes:"prev_button"}, - {name: "weekNumber", classes: "contentSection", ontap: "weekTapped", popup: "popupInput"}, - {name: "popupInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "popupShown", onHide: "popupHidden", components:[ - {classes:"inputContainer", components:[ - {name: "yearInput", kind: "onyx.Input", placeholder: "Type Year here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, - {content: "년", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, - {name: "weekInput", kind: "onyx.Input", placeholder: "Type Week here", classes:"Typing", style: "margin: 10px", onkeypress:"enterDetected"}, - {content: "주", style: "position: relative; top: 10px; margin: 5px; font-weight: bold; font-size: 18px"}, - ]}, - {tag: "br"}, - {tag: "br"}, - {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, - {kind: "onyx.Button", content: "Apply", ontap: "ApplyYearWeek", classes: "popupButton", popup: "showMessage"}, - {name: "showMessage", kind: "onyx.Popup", onkeypress:"closeMessagePopup2", centered: true, modal: true, floating: true, components:[ - {name:"popupContents", content:"", allowHtml: true, style:"text-align: center"}, - {tag: "br"}, - {kind:"onyx.Button", content: "Close", ontap: "closeMessagePopup", style:"position:relative; left: 50%; margin-left: -39.5px"} - ]} - ]}, - {kind: "onyx.IconButton", src: "assets/right_arrow.png", ontap:"rightTapped", classes:"next_button"} - ]}, - {name: "weekTable", kind: "enyo.Table", components: [ - - ]} - ], - published:{ - "setYear":"", - "setWeek":"" - }, - create: function() { - if(!localStorage.count_w){ - localStorage.setItem('count_w', '0'); - } - this.inherited(arguments); - var currentRow, - dateObj = new Date(); - - this.setYear = dateObj.getFullYear(); - this.setWeek = this.getWeekNumber(this.setYear, dateObj.getMonth(), dateObj.getDate()); - - var currentDate = dateObj.getDate(); - var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - var dayOffset = dateObj.getDay(); - var sundayDate = currentDate - dayOffset; - - for( var i = 0; i < 7; i++){ - if(i %7 == 0){ - currentRow = this.$.weekTable.createComponent({}); - } - - if(sundayDate < 1){ - sundayDate += this.getDaysInMonth(dateObj.getMonth()-1, dateObj.getYear()); - } - if(sundayDate + i > this.getDaysInMonth(dateObj.getMonth(), dateObj.getYear())){ - sundayDate -= this.getDaysInMonth(dateObj.getMonth(), dateObj.getYear()); - } - var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; - cellDay = enyo.mixin(cellDay, {classes: "header"}); - if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - for (var i = 0; i < 24; i++){ - currentRow = this.$.weekTable.createComponent({}); - for(var j = 0; j < 7 ; j++){ - var cellTime = new functionCell_W(); - cellTime.number = ((i<19)?i:(i-24)) + 5; - cellTime.year = this.setYear; - cellTime.week = this.setWeek; - cellTime.day = j; - if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) - } - currentRow.createComponent(cellTime); - } - } - - this.$.weekNumber.setContent(this.setYear + "년 " + this.setWeek + "주"); - }, - // adapted from http://stackoverflow.com/questions/1810984/number-of-days-in-any-month - getDaysInMonth: function(m, y) { - return (/8|3|5|10/).test(m)?30:m==1?((y%4===0)&&y%100)||(y%400===0)?29:28:31; - }, - getWeekNumber: function(year, month, date){ - d = new Date(); - d.setHours(0,0,0); - d.setFullYear(year, month, date); - // Set to nearest Thursday: current date + 4 - current day number - // Make Sunday's day number 7 - d.setDate(d.getDate() + 4 - (d.getDay()||7)); - // Get first day of yearc - var yearStart = new Date(year,0,1); - // Calculate full weeks to nearest Thursday - var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7); - // Return array of year and week number - if(yearStart.getDay() == 6){ - if((this.getDaysInMonth( 1, year) == 29) && (month == 11) && (date == 31)){ - return weekNo +2; - } - return weekNo +1; - } - else{ - return weekNo; - } - }, - - leftTapped: function(inSender, inEvent){ - this.$.weekTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - - // calculate current date - var currentDate = dateObj.getDate(); - var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - this.setWeek -= 1; - if(this.setWeek < 1){ - var lastWeek = new Date(); - lastWeek.setFullYear((this.setYear-1), 11, 31); - var lastWeekFirstDate = lastWeek.getDate() - lastWeek.getDay(); - firstWeek = new Date(); - firstWeek.setFullYear(this.setYear, 0, 1); - var firstWeekFirstDate = firstWeek.getDate() - ((firstWeek.getDay() == 0)? firstWeek.getDay() : (firstWeek.getDay() - 31)); - if(lastWeekFirstDate == firstWeekFirstDate){ - this.setWeek = this.getWeekNumber(lastWeek.getFullYear(), lastWeek.getMonth(), lastWeek.getDate()) - 1; - } - else { - this.setWeek = this.getWeekNumber(lastWeek.getFullYear(), lastWeek.getMonth(), lastWeek.getDate()); - } - this.setYear -= 1; - } - var yearStart = new Date(this.setYear, 0, 1); - var firstSunday = yearStart.getDate() - yearStart.getDay(); - if(firstSunday < 1 ){ - firstSunday += 31; - } - var sundayDate = firstSunday; - var count = 12; - for(var i = 1; i < this.setWeek ; i++){ - sundayDate += 7; - if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ - sundayDate -= this.getDaysInMonth(count%12, this.setYear); - count++; - } - } - for( var i = 0; i < 7; i++){ - if(i %7 == 0){ - currentRow = this.$.weekTable.createComponent({}); - } - - if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ - sundayDate -= this.getDaysInMonth(count, this.setYear); - } - var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; - cellDay = enyo.mixin(cellDay, {classes: "header"}); - if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - for (var i = 0; i < 24; i++){ - currentRow = this.$.weekTable.createComponent({}); - for(var j = 0; j < 7 ; j++){ - var cellTime = new functionCell_W(); - cellTime.number = ((i<19)?i:(i-24)) + 5; - cellTime.year = this.setYear; - cellTime.week = this.setWeek; - cellTime.day = j; - if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) - } - currentRow.createComponent(cellTime); - } - } - - - this.$.weekNumber.setContent(this.setYear + "년 " + this.setWeek + "주"); - this.$.weekTable.render(); - }, - - rightTapped: function(inSender, inEvent){ - this.$.weekTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - - // calculate current date - var currentDate = dateObj.getDate(); - var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - this.setWeek += 1; - if(this.setWeek == 53){ - var yearStart = new Date(this.setYear, 0, 1); - var firstSunday = yearStart.getDate() - yearStart.getDay(); - if(firstSunday < 1 ){ - firstSunday += 31; - } - var sundayDate = firstSunday; - var count = 12; - for(var i = 1; i < this.setWeek ; i++){ - sundayDate += 7; - if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ - sundayDate -= this.getDaysInMonth(count%12, this.setYear); - count++; - } - } - firstWeek = new Date(); - firstWeek.setFullYear((this.setYear+1), 0, 1); - var firstWeekFirstDate = firstWeek.getDate() - ((firstWeek.getDay() == 0)? firstWeek.getDay() : (firstWeek.getDay() - 31)); - if(sundayDate == firstWeekFirstDate){ - this.setWeek = 1; - this.setYear += 1; - } - } - else if(this.setWeek == 54){ - this.setWeek = 1; - this.setYear += 1; - } - var yearStart = new Date(this.setYear, 0, 1); - var firstSunday = yearStart.getDate() - yearStart.getDay(); - if(firstSunday < 1 ){ - firstSunday += 31; - } - var sundayDate = firstSunday; - var count = 12; - for(var i = 1; i < this.setWeek ; i++){ - sundayDate += 7; - if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ - sundayDate -= this.getDaysInMonth(count%12, this.setYear); - count++; - } - } - for( var i = 0; i < 7; i++){ - if(i %7 == 0){ - currentRow = this.$.weekTable.createComponent({}); - } - - if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ - sundayDate -= this.getDaysInMonth(count, this.setYear); - } - var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; - cellDay = enyo.mixin(cellDay, {classes: "header"}); - if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - for (var i = 0; i < 24; i++){ - currentRow = this.$.weekTable.createComponent({}); - for(var j = 0; j < 7 ; j++){ - var cellTime = new functionCell_W(); - cellTime.number = ((i<19)?i:(i-24)) + 5; - cellTime.year = this.setYear; - cellTime.week = this.setWeek; - cellTime.day = j; - if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) - } - currentRow.createComponent(cellTime); - } - } - - - this.$.weekNumber.setContent(this.setYear + " 년 " + this.setWeek + " 주"); - this.$.weekTable.render(); - }, - - weekTapped: function(inSender, inEvent){ - this.$.popupInput.show(); - }, - - closePopup: function(inSender, inEvent){ - this.$.popupInput.hide(); - }, - - closeMessagePopup: function(inSender, inEvent){ - this.$.showMessage.hide(); - }, - - popupShown: function() { - this.$.yearInput.focus(); - }, - - isInt: function(value){ - return typeof(value) === 'number' && value % 1 == 0; - }, - - ApplyYearWeek: function(inSender, inEvent){ - var yearInputValue = parseFloat(this.$.yearInput.getValue()); - var weekInputValue = parseFloat(this.$.weekInput.getValue()); - if(this.$.yearInput.getValue() == ""){ - this.$.popupContents.setContent("please input Year value!"); - this.$.showMessage.show(); - return; - } - if(this.$.weekInput.getValue() == ""){ - this.$.popupContents.setContent("please input Week value!"); - this.$.showMessage.show(); - return; - } - if(this.isInt(yearInputValue) == false){ - this.$.popupContents.setContent("Invalid Year value!
    please input integer value"); - this.$.showMessage.show(); - return; - } - else if(yearInputValue < 1000 || yearInputValue > 3000){ - this.$.popupContents.setContent("Invalid Year value!
    please input value between 1000 ~ 3000"); - this.$.showMessage.show(); - return; - } - this.setYear = yearInputValue; - if(this.isInt(weekInputValue) == false){ - this.$.popupContents.setContent("Invalid Week value!
    please input integer value"); - this.$.showMessage.show(); - return; - } - else if(weekInputValue < 1 || weekInputValue > this.getWeekNumber(this.setYear, 11, 31)){ - this.$.popupContents.setContent("Invalid Week value!
    please input value between 1 ~ " + this.getWeekNumber(this.setYear, 11, 31)); - this.$.showMessage.show(); - return; - } - this.setWeek = weekInputValue; - this.$.yearInput.clear(); - this.$.weekInput.clear(); - this.$.popupInput.hide(); - this.$.weekTable.destroyComponents(); - var currentRow, - dateObj = new Date(); - - // calculate current date - var currentDate = dateObj.getDate(); - var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - var yearStart = new Date(this.setYear, 0, 1); - var firstSunday = yearStart.getDate() - yearStart.getDay(); - if(firstSunday < 1 ){ - firstSunday += 31; - } - var sundayDate = firstSunday; - var count = 12; - for(var i = 1; i < this.setWeek ; i++){ - sundayDate += 7; - if(sundayDate > this.getDaysInMonth(count%12, this.setYear)){ - sundayDate -= this.getDaysInMonth(count%12, this.setYear); - count++; - } - } - for( var i = 0; i < 7; i++){ - if(i %7 == 0){ - currentRow = this.$.weekTable.createComponent({}); - } - - if(sundayDate + i > this.getDaysInMonth(count, this.setYear)){ - sundayDate -= this.getDaysInMonth(count, this.setYear); - } - var cellDay = {content : dayName[i] + " / " + (sundayDate + i)}; - cellDay = enyo.mixin(cellDay, {classes: "header"}); - if (((dateObj.getHours() > 4)? (sundayDate+i == currentDate): (sundayDate+i == currentDate - 1))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellDay = enyo.mixin(cellDay, {classes: "current"}); - } - currentRow.createComponent(cellDay); - } - for (var i = 0; i < 24; i++){ - currentRow = this.$.weekTable.createComponent({}); - for(var j = 0; j < 7 ; j++){ - var cellTime = new functionCell_W(); - cellTime.number = ((i<19)?i:(i-24)) + 5; - cellTime.year = this.setYear; - cellTime.week = this.setWeek; - cellTime.day = j; - if((((i<19)?i:(i-24)) + 5) == dateObj.getHours() && ((i<19)?(j == dateObj.getDay()):(j == (dateObj.getDay()-1)))&& (this.setYear == dateObj.getFullYear()) && (this.setWeek == this.getWeekNumber(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate()))){ - cellTime = enyo.mixin(cellTime, {classes: "currentTime"}) - } - currentRow.createComponent(cellTime); - } - } - - - this.$.weekNumber.setContent(this.setYear + " 년 " + this.setWeek + " 주"); - this.$.weekTable.render(); - }, - - enterDetected: function(inSender, inEvent){ - if(inEvent.keyCode == 13){ - this.ApplyYearWeek(); - } - }, - - closeMessagePopup2: function(inSender,inEvent){ - if(inEvent.keyCode == 13){ - this.closeMessagePopup(); - } - } -}); - -enyo.kind({ - name:"functionCell_W", - kind:"enyo.TableCell", - components:[ - {name: "cellContent", popup:"scheduleInput", popup:"scheduleShow", content:"", style:"display:inline"}, - {name:"scheduleInput", kind: "onyx.Popup", centered: true, modal: true, floating: true, onShow: "", components:[ - {content: "제목", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, - {name: "subjectInput", kind: "onyx.Input", placeholder: "Type subject here", classes:"Typing", style: "margin: 10px", onkeypress:""}, - {tag:"br"}, - {content: "장소", style: "position: relative; top: 5px; margin: 5px; font-weight: bold; font-size: 18px; display: inline"}, - {name: "placeInput", kind: "onyx.Input", placeholder: "Type Place here", classes:"Typing", style: "margin: 10px", onkeypress:""}, - {tag:"br"}, - {tag:"br"}, - {kind: "onyx.Button", content: "Close", ontap: "closePopup", classes: "popupButton"}, - {kind: "onyx.Button", content: "Apply", ontap: "applySchedule", classes: "popupButton"} - ]}, - {name:"scheduleShow", kind:"onyx.Popup", onHide:"ScheduleListHide", modal: true, floating: true, components:[ - {kind: "onyx.Groupbox", components: [ - {name:"scheduleList", kind: "onyx.GroupboxHeader", content: "Schedule List"} - ]} - ]}, - {name: "scheduleImage", kind:"enyo.Image", src:"assets/dot.png", active: false, style:"float: right; height: 10px; width: 10px;"}, - {name: "schedule", components:[ - {name:"subject", content:""}, - {name:"time", content:""}, - {name:"place", content:""} - ]} - ], - published:{ - active: false, - isSchedule: false, - number: "", - year: "", - week: "", - day: "" - }, - handlers:{ - ontap:"cellTap", - onleave: "cellDeactive" - }, - create: function(){ - this.inherited(arguments); - this.$.cellContent.setContent(this.number); - - for(var i = 1 ; i < parseInt(localStorage.count_w)+1 ; i++){ - if((localStorage.getItem(i.toString()+'w')) != null){ - var Obj = {}; - Obj = JSON.parse(localStorage.getItem(i.toString()+'w')); - if(Obj.year == this.year && Obj.week == this.week && Obj.day == this.day && Obj.hours == this.number){ - this.restoreSchedule(Obj.subject, Obj.time, Obj.place); - } - } - } - - this.$.schedule.hide(); - if(this.isSchedule == false){ - this.$.scheduleImage.hide(); - } - }, - restoreSchedule: function(subject, time, place){ - var newSchedule = new scheduleThing(); - newSchedule.setContent(time + "시에 " + place + "에서 " + subject +"이(가) 있습니다."); - this.$.scheduleList.createComponent(newSchedule); - this.$.scheduleList.render(); - this.isSchedule = true; - this.$.scheduleImage.show(); - }, - cellTap: function(inSender, inEvent){ - if(this.active == false){ - this.active = true; - this.applyStyle("background-color","yellow"); - if(this.isSchedule == true){ - this.$.scheduleShow.showAtEvent(inEvent); - } - } - else if(this.active == true){ - this.$.scheduleInput.show(); - } - }, - cellDeactive: function(inSender, inEvent){ - if(this.active == true){ - this.active = false; - this.applyStyle("background-color", "white"); - if(this.getClassAttribute() == "currentTime"){ - this.applyStyle("background-color", "#226B9A"); - } - } - }, - closePopup: function(inSender, inEvent){ - this.$.scheduleInput.hide(); - }, - - applySchedule: function(inSender, inEvent){ - var subject = this.$.subjectInput.getValue(); - var time = this.$.cellContent.getContent(); - var place = this.$.placeInput.getValue(); - this.$.subjectInput.clear(); - this.$.placeInput.clear(); - - var newSchedule = new scheduleThing(); - newSchedule.setContent(time + "시에 " + place + "에서 " + subject +"이(가) 있습니다."); - var count_w = parseInt(localStorage.count_w); - count_w++; - localStorage.setItem('count_w', count_w); - var Obj_w = []; - Obj_w[count_w] = {year: this.year, week: this.week, day: this.day, hours: this.number, subject: subject, time: time, place: place }; - localStorage.setItem(count_w.toString() + 'w', JSON.stringify(Obj_w[count_w])); - this.$.scheduleList.createComponent(newSchedule); - this.$.scheduleList.render(); - this.isSchedule = true; - this.$.scheduleImage.show(); - this.$.scheduleInput.hide(); - }, - - ScheduleListHide: function(inSender, inEvent){ - if(this.active == false){ - this.active = true; - this.applyStyle("background-color","yellow"); - } - } -}); - -enyo.kind({ - name: "scheduleThing", - content: "", - handlers:{ - ontap: "editSchedule" - } -}); \ No newline at end of file diff --git a/source/package.js b/source/package.js deleted file mode 100644 index 7da252c..0000000 --- a/source/package.js +++ /dev/null @@ -1,8 +0,0 @@ -enyo.depends( - "$lib/layout", - "$lib/onyx", // To theme Onyx using Theme.less, change this line to $lib/onyx/source, - //"Theme.less", // uncomment this line, and follow the steps described in Theme.less - "Scheduler.css", - "Scheduler.js", - "function" -); diff --git a/tools/deploy.bat b/tools/deploy.bat deleted file mode 100644 index 3138635..0000000 --- a/tools/deploy.bat +++ /dev/null @@ -1,37 +0,0 @@ -@REM don't watch the sausage being made -@ECHO OFF - -REM the folder this script is in (*/bootplate/tools) -SET TOOLS=%~DP0 - -REM enyo location -SET ENYO=%TOOLS%\..\enyo - -REM deploy script location -SET DEPLOY=%ENYO%\tools\deploy.js - -REM node location -SET NODE=node.exe - -REM use node to invoke deploy.js with imported parameters -%NODE% "%DEPLOY%" %* - -REM copy files and package if deploying to cordova webos -:again -if not "%1" == "" ( - - if "%1" == "--cordova-webos" ( - REM copy appinfo.json and cordova*.js files - SET SRC=%TOOLS%..\ - for %%A in ("%~dp0./..") do SET DEST=%TOOLS%..\deploy\%%~nA - copy %SRC%appinfo.json %DEST% - copy %SRC%cordova*.js %DEST% - - REM package it up - if not exist %SRC%bin mkdir %SRC%bin - palm-package.bat %DEST% --outdir=%SRC%bin - ) - - shift - goto again -) diff --git a/tools/deploy.sh b/tools/deploy.sh deleted file mode 100644 index e9af9fd..0000000 --- a/tools/deploy.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# the folder this script is in (*/bootplate/tools) -TOOLS=$(cd `dirname $0` && pwd) - -# enyo location -ENYO="$TOOLS/../enyo" - -# deploy script location -DEPLOY="$ENYO/tools/deploy.js" - -# check for node, but quietly -if command -v node >/dev/null 2>&1; then - # use node to invoke deploy with imported parameters - echo "enyo/tools/minify.sh args: " $@ - node "$DEPLOY" $@ -else - echo "No node found in path" - exit 1 -fi - -# copy files and package if deploying to cordova webos -while [ "$1" != "" ]; do - case $1 in - -w | --cordova-webos ) - # copy appinfo.json and cordova*.js files - SRC="$TOOLS/../" - DEST="$TOOLS/../deploy/"${PWD##*/} - - cp "$SRC"appinfo.json $DEST -v - cp "$SRC"cordova*.js $DEST -v - - # package it up - mkdir -p "$DEST/bin" - palm-package "$DEST/bin" - ;; - esac - shift -done From 59a64e3b91cd605914e0859e5347e62e73e386d1 Mon Sep 17 00:00:00 2001 From: Saramean Date: Fri, 20 Jun 2014 16:54:08 +0900 Subject: [PATCH 3/3] Saramean's commit --- gallery_images/Saramean.scheduler.jpg | Bin 0 -> 37999 bytes gallery_manifest.json | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 gallery_images/Saramean.scheduler.jpg diff --git a/gallery_images/Saramean.scheduler.jpg b/gallery_images/Saramean.scheduler.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6ce97bdb781b6d1f48620afe1789d7bfa42b5f0 GIT binary patch literal 37999 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 literal 0 HcmV?d00001 diff --git a/gallery_manifest.json b/gallery_manifest.json index bf56746..9625cd9 100644 --- a/gallery_manifest.json +++ b/gallery_manifest.json @@ -1,5 +1,10 @@ { "owners": { + "Saramean": { + "name": "Taehwa Kang", + "website": "", + "twitter": "" + }, "dimitrk": { "name": "DimitrK", "website": "http://www.appopsi.com", @@ -186,6 +191,24 @@ } }, "widgets": [ + { + "name": "Saramean.scheduler", + "displayName": "Scheduler", + "owner": "Saramean", + "dependencies": [ + { + "name": "Enyo 2", + "version": "" + } + ], + "url": "https://github.com/Saramean/scheduler", + "demoUrl": "", + "submissionDate": "June 20, 2014", + "testedPlatforms": "IE 10 (windows 7), Chrome 32.0.1700.72 (windows 7)", + "license": "", + "version": "1.0", + "blurb": "Enyo scheduler application." + }, { "name": "dimitrk.enigma", "displayName": "Enigma",

    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 ZSV=`|o|&s+m?^$49RAnC{{`^0FP}7Ec+T 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 diff --git a/lib/layout/imageview/samples/assets/uranus.jpg b/lib/layout/imageview/samples/assets/uranus.jpg deleted file mode 100644 index 0a8fbc2c554e41f658e73dcd642849b1c2a82838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46984 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%0DD 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 diff --git a/lib/layout/imageview/samples/package.js b/lib/layout/imageview/samples/package.js deleted file mode 100644 index c6c33c8..0000000 --- a/lib/layout/imageview/samples/package.js +++ /dev/null @@ -1,6 +0,0 @@ -enyo.depends( - "ImageViewSample.js", - "ImageViewSample.css", - "ImageCarouselSample.js", - "ImageCarouselSample.css" -); \ No newline at end of file diff --git a/lib/layout/imageview/source/ImageCarousel.js b/lib/layout/imageview/source/ImageCarousel.js deleted file mode 100644 index 1edacf6..0000000 --- a/lib/layout/imageview/source/ImageCarousel.js +++ /dev/null @@ -1,208 +0,0 @@ -/** - _enyo.ImageCarousel_ is an enyo.Panels that - uses enyo.CarouselArranger as its - arrangerKind. An ImageCarousel dynamically creates and loads instances of - enyo.ImageView as needed, creating a gallery - of images. - - {kind:"ImageCarousel", images:[ - "assets/mercury.jpg", - "assets/venus.jpg", - "assets/earth.jpg", - "assets/mars.jpg", - "assets/jupiter.jpg", - "assets/saturn.jpg", - "assets/uranus.jpg", - "assets/neptune.jpg" - ], defaultScale:"auto"}, - - All of the events (_onload_, _onerror_, and _onZoom_) from the contained - ImageView objects are bubbled up to the ImageCarousel, which also inherits - the _onTransitionStart_ and _onTransitionFinish_ events from _enyo.Panels_. - - The _images_ property is an array containing the file paths of the images in - the gallery. The _images_ array may be altered and updated at any time, and - the current index may be manipulated at runtime via the inherited - _getIndex()_ and _setIndex()_ functions. - - Note that it's best to specify a size for the ImageCarousel in order to - avoid complications. -*/ - -enyo.kind({ - name: "enyo.ImageCarousel", - kind: enyo.Panels, - arrangerKind: "enyo.CarouselArranger", - /** - The default scale value to be applied to each ImageView. Can be "auto", - "width", "height", or any positive numeric value. - */ - defaultScale: "auto", - //* If true, ImageView instances are created with zooming disabled. - disableZoom: false, - /** - If true, any ImageViews that are not in the immediate viewing area - (i.e., the currently active image and the first image on either - side of it) will be destroyed to free up memory. This has the benefit of - using minimal memory (which is good for mobile devices), but has the - downside that, if you want to view the images again, the ImageViews will - have to be re-created and the images re-fetched (thus increasing the - number of image-related GET calls). Defaults to false. - */ - lowMemory: false, - published: { - //* Array of image source file paths - images:[] - }, - //* @protected - handlers: { - onTransitionStart: "transitionStart", - onTransitionFinish: "transitionFinish" - }, - create: function() { - this.inherited(arguments); - this.imageCount = this.images.length; - if(this.images.length>0) { - this.initContainers(); - this.loadNearby(); - } - }, - initContainers: function() { - for(var i=0; i=0 && x<=xEnd) { - c = this.$["container" + i]; - x+= c.width + c.marginWidth; - range.unshift(i); - i--; - } - // get the upper range - i=this.index; - x=0; - xEnd = bounds.width * (prefetchRange + 1); - while (i=0 && index<=this.images.length-1) { - if(!this.$["image" + index]) { - this.$["container" + index].createComponent({ - name: "image" + index, - kind: "ImageView", - scale: this.defaultScale, - disableZoom: this.disableZoom, - src: this.images[index], - verticalDragPropagation: false, - style: "height:100%; width:100%;" - }, {owner: this}); - this.$["image" + index].render(); - } else { - if(this.$["image" + index].src != this.images[index]) { - this.$["image" + index].setSrc(this.images[index]); - this.$["image" + index].setScale(this.defaultScale); - this.$["image" + index].setDisableZoom(this.disableZoom); - } - } - } - return this.$["image" + index]; - }, - setImages: function(inImages) { - // always invoke imagesChanged because this is an array property - // which might otherwise seem to be the same object - this.setPropertyValue("images", inImages, "imagesChanged"); - }, - imagesChanged: function() { - this.initContainers(); - this.loadNearby(); - }, - indexChanged: function() { - this.loadNearby(); - if(this.lowMemory) { - this.cleanupMemory(); - } - this.inherited(arguments); - }, - transitionStart: function(inSender, inEvent) { - if(inEvent.fromIndex==inEvent.toIndex) - return true; //prevent from bubbling if there's no change - }, - transitionFinish: function(inSender, inEvent) { - this.loadNearby(); - if(this.lowMemory) { - this.cleanupMemory(); - } - }, - //* @public - //* Returns the currently displayed ImageView. - getActiveImage: function() { - return this.getImageByIndex(this.index); - }, - //* Returns the ImageView with the specified index. - getImageByIndex: function(index) { - return this.$["image" + index] || this.loadImageView(index); - }, - /** - Destroys any ImageView objects that are not in the immediate viewing - area (i.e., the currently active image and the first image on either - side of it) to free up memory. If you set the Image Carousel's - _lowMemory_ property to true, this function will be called automatically - as needed. - */ - cleanupMemory: function() { - var buffer = getBufferRange(); - for(var i=0; ienyo.ScrollThumb - indicators, disable zoom animation, allow panning overscroll (with a - bounce-back effect), and control the propagation of drag events, all via - boolean properties. - - Note that it's best to specify a size for the ImageView in order to avoid - complications. -*/ - -enyo.kind({ - name: "enyo.ImageView", - kind: enyo.Scroller, - /** - If true, allows for overscrolling during panning, with a bounce-back - effect. (Defaults to false.) - */ - touchOverscroll: false, - /** - If true, a ScrollThumb is used to indicate scroll position/bounds. - (Defaults to false.) - */ - thumb: false, - /** - If true (the default), the zoom action triggered by a double-tap (or - double-click) will be animated. - */ - animate: true, - /** - If true (the default), allows propagation of vertical drag events when - already at the top or bottom of the pannable area. - */ - verticalDragPropagation: true, - /** - If true (the default), allows propagation of horizontal drag events when - already at the left or right edge of the pannable area. - */ - horizontalDragPropagation: true, - published: { - /** - The scale at which the image should be displayed. It may be any - positive numeric value or one of the following key words (which will - be resolved to a value dynamically): - - * "auto": Fits the image to the size of the ImageView - * "width": Fits the image the width of the ImageView - * "height": Fits the image to the height of the ImageView - * "fit": Fits the image to the height and width of the ImageView. - Overflow of the larger dimension is cropped and the image is centered - on this axis - */ - scale: "auto", - //* Disables the zoom functionality - disableZoom: false, - //* The file path of the image to be displayed - src: undefined - }, - events: { - /** - Fires whenever the user adjusts the zoom of the image, via - double-tap/double-click, mousewheel, or pinch-zoom. - - _inEvent.scale_ contains the new scaling factor for the image. - */ - onZoom:"" - }, - //* @protected - touch: true, - preventDragPropagation: false, - handlers: { - ondragstart: "dragPropagation" - }, - components:[ - {name: "animator", kind: "Animator", onStep: "zoomAnimationStep", onEnd: "zoomAnimationEnd"}, - {name:"viewport", style: "overflow:hidden;min-height:100%;min-width:100%;", classes: "enyo-fit", - ongesturechange: "gestureTransform", ongestureend: "saveState", ontap: "singleTap", - ondblclick: "doubleClick", onmousewheel: "mousewheel", - components: [ - {kind:"Image", ondown: "down"} - ] - } - ], - create: function() { - this.inherited(arguments); - this.canTransform = enyo.dom.canTransform(); - if(!this.canTransform) { - this.$.image.applyStyle("position", "relative"); - } - this.canAccelerate = enyo.dom.canAccelerate(); - //offscreen buffer image to get initial image dimensions - //before displaying a scaled down image that can fit in the container - this.bufferImage = new Image(); - this.bufferImage.onload = enyo.bind(this, "imageLoaded"); - this.bufferImage.onerror = enyo.bind(this, "imageError"); - this.srcChanged(); - // For image view, disable drags during gesture (to fix flicker: ENYO-1208) - this.getStrategy().setDragDuringGesture(false); - // Needed to kickoff pin redrawing (otherwise they wont' redraw on intitial scroll) - if(this.getStrategy().$.scrollMath) { - this.getStrategy().$.scrollMath.start(); - } - }, - down: function(inSender, inEvent) { - // Fix to prevent image drag in Firefox - inEvent.preventDefault(); - }, - dragPropagation: function(inSender, inEvent) { - // Propagate drag events at the edges of the image as desired by the - // verticalDragPropagation and horizontalDragPropagation properties - var bounds = this.getStrategy().getScrollBounds(); - var verticalEdge = ((bounds.top===0 && inEvent.dy>0) || (bounds.top>=bounds.maxTop-2 && inEvent.dy<0)); - var horizontalEdge = ((bounds.left===0 && inEvent.dx>0) || (bounds.left>=bounds.maxLeft-2 && inEvent.dx<0)); - return !((verticalEdge && this.verticalDragPropagation) || (horizontalEdge && this.horizontalDragPropagation)); - }, - mousewheel: function(inSender, inEvent) { - inEvent.pageX |= (inEvent.clientX + inEvent.target.scrollLeft); - inEvent.pageY |= (inEvent.clientY + inEvent.target.scrollTop); - var zoomInc = (this.maxScale - this.minScale)/10; - var oldScale = this.scale; - if((inEvent.wheelDelta > 0) || (inEvent.detail < 0)) { //zoom in - this.scale = this.limitScale(this.scale + zoomInc); - } else if((inEvent.wheelDelta < 0) || (inEvent.detail > 0)) { //zoom out - this.scale = this.limitScale(this.scale - zoomInc); - } - this.eventPt = this.calcEventLocation(inEvent); - this.transformImage(this.scale); - if(oldScale != this.scale) { - this.doZoom({scale:this.scale}); - } - this.ratioX = this.ratioY = null; - // Prevent default scroll wheel action and prevent event from bubbling up to to touch scroller - inEvent.preventDefault(); - return true; - }, - srcChanged: function() { - if(this.src && this.src.length>0 && this.bufferImage && this.src!=this.bufferImage.src) { - this.bufferImage.src = this.src; - } - }, - imageLoaded: function(inEvent) { - this.originalWidth = this.bufferImage.width; - this.originalHeight = this.bufferImage.height; - - //scale to fit before setting src, so unscaled image isn't visible - this.scaleChanged(); - this.$.image.setSrc(this.bufferImage.src); - - //Needed to ensure scroller contents height/width is calculated correctly when contents use enyo-fit - enyo.dom.transformValue(this.getStrategy().$.client, "translate3d", "0px, 0px, 0"); - - this.positionClientControls(this.scale); - this.alignImage(); - }, - resizeHandler: function() { - this.inherited(arguments); - // Once we've loaded the image, adjust the min/max scale anytime we resize - if (this.$.image.src) { - this.scaleChanged(); - } - }, - scaleChanged: function() { - var containerNode = this.hasNode(); - if(containerNode) { - this.containerWidth = containerNode.clientWidth; - this.containerHeight = containerNode.clientHeight; - var widthScale = this.containerWidth / this.originalWidth; - var heightScale = this.containerHeight / this.originalHeight; - this.minScale = Math.min(widthScale, heightScale); - this.maxScale = (this.minScale*3 < 1) ? 1 : this.minScale*3; - //resolve any keyword scale values to solid numeric values - if(this.scale == "auto") { - this.scale = this.minScale; - } else if(this.scale == "width") { - this.scale = widthScale; - } else if(this.scale == "height") { - this.scale = heightScale; - } else if(this.scale == "fit") { - this.fitAlignment = "center"; - this.scale = Math.max(widthScale, heightScale); - } else { - this.maxScale = Math.max(this.maxScale, this.scale); - this.scale = this.limitScale(this.scale); - } - } - this.eventPt = this.calcEventLocation(); - this.transformImage(this.scale); - }, - imageError: function(inEvent) { - enyo.error("Error loading image: " + this.src); - //bubble up the error event - this.bubble("onerror", inEvent); - }, - alignImage: function() { - if (this.fitAlignment && this.fitAlignment === "center") { - var sb = this.getScrollBounds(); - this.setScrollLeft( sb.maxLeft / 2); - this.setScrollTop( sb.maxTop / 2); - } - }, - gestureTransform: function(inSender, inEvent) { - this.eventPt = this.calcEventLocation(inEvent); - this.transformImage(this.limitScale(this.scale * inEvent.scale)); - }, - calcEventLocation: function(inEvent) { - //determine the target coordinates on the imageview from an event - var eventPt = {x: 0, y:0}; - if(inEvent && this.hasNode()) { - var rect = this.node.getBoundingClientRect(); - eventPt.x = Math.round((inEvent.pageX - rect.left) - this.imageBounds.x); - eventPt.x = Math.max(0, Math.min(this.imageBounds.width, eventPt.x)); - eventPt.y = Math.round((inEvent.pageY - rect.top) - this.imageBounds.y); - eventPt.y = Math.max(0, Math.min(this.imageBounds.height, eventPt.y)); - } - return eventPt; - }, - transformImage: function(scale) { - this.tapped = false; - - var prevBounds = this.imageBounds || this.innerImageBounds(scale); - this.imageBounds = this.innerImageBounds(scale); - - //style cursor if needed to indicate the image is movable - if(this.scale>this.minScale) { - this.$.viewport.applyStyle("cursor", "move"); - } else { - this.$.viewport.applyStyle("cursor", null); - } - this.$.viewport.setBounds({width: this.imageBounds.width + "px", height: this.imageBounds.height + "px"}); - - //determine the exact ratio where on the image was tapped - this.ratioX = this.ratioX || (this.eventPt.x + this.getScrollLeft()) / prevBounds.width; - this.ratioY = this.ratioY || (this.eventPt.y + this.getScrollTop()) / prevBounds.height; - var scrollLeft, scrollTop; - if(this.$.animator.ratioLock) { //locked for smartzoom - scrollLeft = (this.$.animator.ratioLock.x * this.imageBounds.width) - (this.containerWidth / 2); - scrollTop = (this.$.animator.ratioLock.y * this.imageBounds.height) - (this.containerHeight / 2); - } else { - scrollLeft = (this.ratioX * this.imageBounds.width) - this.eventPt.x; - scrollTop = (this.ratioY * this.imageBounds.height) - this.eventPt.y; - } - scrollLeft = Math.max(0, Math.min((this.imageBounds.width - this.containerWidth), scrollLeft)); - scrollTop = Math.max(0, Math.min((this.imageBounds.height - this.containerHeight), scrollTop)); - - if(this.canTransform) { - var params = {scale: scale}; - // translate needs to be first, or scale and rotation will not be in the correct spot - if(this.canAccelerate) { - //translate3d rounded values to avoid distortion; ref: http://martinkool.com/post/27618832225/beware-of-half-pixels-in-css - params = enyo.mixin({translate3d: Math.round(this.imageBounds.left) + "px, " + Math.round(this.imageBounds.top) + "px, 0px"}, params); - } else { - params = enyo.mixin({translate: this.imageBounds.left + "px, " + this.imageBounds.top + "px"}, params); - } - enyo.dom.transform(this.$.image, params); - } else { //pretty much just IE8 - //use top/left and width/height to adjust - this.$.image.setBounds({width: this.imageBounds.width + "px", height: this.imageBounds.height + "px", - left:this.imageBounds.left + "px", top:this.imageBounds.top + "px"}); - } - - //adjust scroller to new position that keeps ratio with the new image size - this.setScrollLeft(scrollLeft); - this.setScrollTop(scrollTop); - - this.positionClientControls(scale); - - //this.stabilize(); - }, - limitScale: function(scale) { - if(this.disableZoom) { - scale = this.scale; - } else if(scale > this.maxScale) { - scale = this.maxScale; - } else if(scale < this.minScale) { - scale = this.minScale; - } - return scale; - }, - innerImageBounds: function(scale) { - var width = this.originalWidth * scale; - var height = this.originalHeight * scale; - var offset = {x:0, y:0, transX:0, transY:0}; - if(width - - - - FlyweightRepeater Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/FlyweightRepeaterSample.js b/lib/layout/list/samples/FlyweightRepeaterSample.js deleted file mode 100644 index 5733a97..0000000 --- a/lib/layout/list/samples/FlyweightRepeaterSample.js +++ /dev/null @@ -1,59 +0,0 @@ -enyo.kind({ - name: "enyo.sample.FlyweightRepeaterSample", - kind: "FittableRows", - classes: "flyweight-repeater-sample enyo-fit onyx", - components: [ - {kind: "onyx.Toolbar", components: [ - {content: "FlyweightRepeater Result"} - ]}, - {name:"result", style:"padding:12px; font-size: 20px;", content: "Nothing selected yet."}, - {kind: "enyo.Scroller", fit: true, components: [ - {name:"repeater", kind:"enyo.FlyweightRepeater", classes:"flyweight-repeater-sample-list", count: 26, onSetupItem: "setupItem", components: [ - {name: "item", classes:"flyweight-repeater-sample-item"} - ]} - ]} - ], - handlers: { - onSelect: "itemSelected" - }, - people: [ - {name: "Andrew"}, - {name: "Betty"}, - {name: "Christopher"}, - {name: "Donna"}, - {name: "Ephraim"}, - {name: "Frankie"}, - {name: "Gerald"}, - {name: "Heather"}, - {name: "Ingred"}, - {name: "Jack"}, - {name: "Kevin"}, - {name: "Lucy"}, - {name: "Matthew"}, - {name: "Noreen"}, - {name: "Oscar"}, - {name: "Pedro"}, - {name: "Quentin"}, - {name: "Ralph"}, - {name: "Steven"}, - {name: "Tracy"}, - {name: "Uma"}, - {name: "Victor"}, - {name: "Wendy"}, - {name: "Xin"}, - {name: "Yulia"}, - {name: "Zoltan"} - ], - setupItem: function(inSender, inEvent) { - var index = inEvent.index; - this.$.item.setContent((index+1) + ". " + this.people[index].name); - this.$.item.applyStyle("background", (inEvent.selected? "dodgerblue":"lightgray")); - }, - itemSelected: function(inSender, inEvent) { - var index = inEvent.index; - var count = inEvent.flyweight.count; - if(index>=0 && index * { - display: inline-block; - vertical-align: middle; -} -.list-sample-around-avatar { - width: 32px; - height: 32px; - padding-right: 10px; -} -.list-sample-around-name { - font-size: 16px; - font-weight: bold; - color: white; -} -.list-sample-around-description { - font-size: 12px; - color: silver; -} -.list-sample-around-remove-button { - float: right; - display: none; -} -/* divider */ -.list-sample-around-divider { - background-color: #666; - font-size: 14px; - font-weight: bold; - padding: 8px 14px; -} -/* popup */ -.list-sample-around-popup { - width: 280px; -} -.list-sample-around-popup > * { - display: block; - margin: 10px 10px; -} -.list-sample-around-populate-button { - float: right; - margin-top: 25px; -} -.list-sample-around-label { - display: inline-block; - width: 120px; - padding-right: 10px; -} \ No newline at end of file diff --git a/lib/layout/list/samples/ListAroundSample.html b/lib/layout/list/samples/ListAroundSample.html deleted file mode 100644 index 35422fe..0000000 --- a/lib/layout/list/samples/ListAroundSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - AroundList Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListAroundSample.js b/lib/layout/list/samples/ListAroundSample.js deleted file mode 100644 index 6350161..0000000 --- a/lib/layout/list/samples/ListAroundSample.js +++ /dev/null @@ -1,211 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListAroundSample", - kind: "FittableRows", - classes: "enyo-fit enyo-unselectable", - components: [ - {name: "list", kind: "AroundList", classes: "list-sample-around", fit: true, multiSelect: true, onSetupItem: "setupItem", aboveComponents: [ - {kind: "onyx.Toolbar", layoutKind: "FittableColumnsLayout", components: [ - {kind: "onyx.InputDecorator", fit: true, noStretch: true, layoutKind: "FittableColumnsLayout", components: [ - {kind: "onyx.Input", placeholder: "Search...", fit: true, oninput: "searchInputChange"}, - {kind: "Image", src: "assets/search-input-search.png", style: "height: 20px; width: 20px;"} - ]} - ]} - ], components: [ - {name: "divider", classes: "list-sample-around-divider"}, - {name: "item", kind: "AroundListContactItem", classes: "list-sample-around-item enyo-border-box", onRemove: "removeTap"} - ]}, - {name: "popup", kind: "onyx.Popup", modal: true, centered: true, classes: "list-sample-around-popup", components: [ - {components: [ - {content: "count:", classes: "list-sample-around-label"}, - {kind: "onyx.InputDecorator", components: [ - {name: "countInput", kind: "onyx.Input", style: "width: 80px", value: 100} - ]} - ]}, - {components: [ - {content: "rowsPerPage:", classes: "list-sample-around-label"}, - {kind: "onyx.InputDecorator", components: [ - {name: "rowsPerPageInput", kind: "onyx.Input", style: "width: 80px", value: 50} - ]} - ]}, - {components: [ - {content: "hide divider:", classes: "list-sample-around-label"}, - {name: "hideDividerCheckbox", kind: "onyx.Checkbox"} - ]}, - {components: [ - {kind: "onyx.Button", content: "populate list", classes: "list-sample-around-populate-button", ontap: "populateList"} - ]} - ]} - ], - rendered: function() { - this.inherited(arguments); - this.populateList(); - }, - setupItem: function(inSender, inEvent) { - var i = inEvent.index; - var data = this.filter ? this.filtered : this.db; - var item = data[i]; - // content - this.$.item.setContact(item); - // selection - this.$.item.setSelected(inSender.isSelected(i)); - // divider - if (!this.hideDivider) { - var d = item.name[0]; - var prev = data[i-1]; - var showd = d != (prev && prev.name[0]); - this.$.divider.setContent(d); - this.$.divider.canGenerate = showd; - this.$.item.applyStyle("border-top", showd ? "none" : null); - } - }, - refreshList: function() { - if (this.filter) { - this.filtered = this.generateFilteredData(this.filter); - this.$.list.setCount(this.filtered.length); - } else { - this.$.list.setCount(this.db.length); - } - this.$.list.refresh(); - }, - addItem: function() { - var item = this.generateItem(enyo.cap(this.$.newContactInput.getValue())); - var i = 0; - for (var di; (di=this.db[i]); i++) { - if (di.name > item.name) { - this.db.splice(i, 0, item); - break; - } - } - this.refreshList(); - this.$.list.scrollToRow(i); - }, - removeItem: function(inIndex) { - this._removeItem(inIndex); - this.refreshList(); - this.$.list.getSelection().deselect(inIndex); - }, - _removeItem: function(inIndex) { - var i = this.filter ? this.filtered[inIndex].dbIndex : inIndex; - this.db.splice(i, 1); - }, - removeTap: function(inSender, inEvent) { - this.removeItem(inEvent.index); - return true; - }, - populateList: function() { - this.$.popup.hide(); - this.createDb(this.$.countInput.getValue()); - this.$.list.setCount(this.db.length); - this.$.list.setRowsPerPage(this.$.rowsPerPageInput.getValue()); - // - this.hideDivider = this.$.hideDividerCheckbox.getValue(); - this.$.divider.canGenerate = !this.hideDivider; - // - this.$.list.reset(); - this.$.list.scrollToContentStart(); - }, - createDb: function(inCount) { - this.db = []; - for (var i=0; i b.name) return 1; - else return 0; - }); - }, - showSetupPopup: function() { - this.$.popup.show(); - }, - searchInputChange: function(inSender) { - enyo.job(this.id + ":search", enyo.bind(this, "filterList", inSender.getValue()), 200); - }, - filterList: function(inFilter) { - if (inFilter != this.filter) { - this.filter = inFilter; - this.filtered = this.generateFilteredData(inFilter); - this.$.list.setCount(this.filtered.length); - this.$.list.reset(); - } - }, - generateFilteredData: function(inFilter) { - var re = new RegExp("^" + inFilter, "i"); - var r = []; - for (var i=0, d; (d=this.db[i]); i++) { - if (d.name.match(re)) { - d.dbIndex = i; - r.push(d); - } - } - return r; - } -}); - -var avatars = [ - "angel.png", - "astrologer.png", - "athlete.png", - "baby.png", - "clown.png", - "devil.png", - "doctor.png", - "dude.png", - "dude2.png", - "dude3.png", - "dude4.png", - "dude5.png", - "dude6.png" -]; -var titles = [ - "Regional Data Producer", - "Internal Markets Administrator", - "Central Solutions Producer", - "Dynamic Program Executive", - "Direct Configuration Executive", - "International Marketing Assistant", - "District Research Consultant", - "Lead Intranet Coordinator", - "Central Accountability Director", - "Product Web Assistant" -]; - -// It's convenient to create a kind for the item we'll render in the contacts list. -enyo.kind({ - name: "AroundListContactItem", - events: { - onRemove: "" - }, - components: [ - {name: "avatar", kind: "Image", classes: "list-sample-around-avatar"}, - {components: [ - {name: "name", classes: "list-sample-around-name"}, - {name: "title", classes: "list-sample-around-description"}, - {content: "(415) 711-1234", classes: "list-sample-around-description"} - ]}, - {name: "remove", kind: "onyx.IconButton", classes: "list-sample-around-remove-button", src: "assets/remove-icon.png", ontap: "removeTap"} - ], - setContact: function(inContact) { - this.$.name.setContent(inContact.name); - this.$.avatar.setSrc(inContact.avatar); - this.$.title.setContent(inContact.title); - }, - setSelected: function(inSelected) { - this.addRemoveClass("list-sample-around-item-selected", inSelected); - this.$.remove.applyStyle("display", inSelected ? "inline-block" : "none"); - }, - removeTap: function(inSender, inEvent) { - this.doRemove(inEvent); - return true; - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.css b/lib/layout/list/samples/ListBasicSample.css deleted file mode 100644 index 5ff4102..0000000 --- a/lib/layout/list/samples/ListBasicSample.css +++ /dev/null @@ -1,28 +0,0 @@ -.list-sample { - background-color: gray; -} -.list-sample-list { - width: 50%; - min-width: 300px; - max-width: 600px; - margin: auto; - background-color: #eee; -} -.list-sample-item { - border: 1px solid silver; - padding: 18px; - font-size: 18px; - font-weight: bold; -} -.list-sample-index { - float: right; - font-size: 16px; - font-weight: normal; -} -.list-sample-selected { - background-color: #c4e3fe; -} -/* needed to make onyx-highlight more specific for highlighting to work */ -.onyx-highlight.list-sample-selected { - background-color: #dedfdf; -} \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.html b/lib/layout/list/samples/ListBasicSample.html deleted file mode 100644 index f261a09..0000000 --- a/lib/layout/list/samples/ListBasicSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Basic List Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListBasicSample.js b/lib/layout/list/samples/ListBasicSample.js deleted file mode 100644 index 056473c..0000000 --- a/lib/layout/list/samples/ListBasicSample.js +++ /dev/null @@ -1,27 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListBasicSample", - classes: "list-sample enyo-fit", - components: [ - {name: "list", kind: "List", count: 20000, multiSelect: false, classes: "enyo-fit list-sample-list", onSetupItem: "setupItem", components: [ - {name: "item", classes: "list-sample-item enyo-border-box", components: [ - {name: "index", classes: "list-sample-index"}, - {name: "name"} - ]} - ]} - ], - names: [], - setupItem: function(inSender, inEvent) { - // this is the row we're setting up - var i = inEvent.index; - // make some mock data if we have none for this row - if (!this.names[i]) { - this.names[i] = makeName(5, 10, '', ''); - } - var n = this.names[i]; - var ni = ("00000000" + i).slice(-7); - // apply selection style if inSender (the list) indicates that this row is selected. - this.$.item.addRemoveClass("list-sample-selected", inSender.isSelected(i)); - this.$.name.setContent(n); - this.$.index.setContent(ni); - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.css b/lib/layout/list/samples/ListContactsSample.css deleted file mode 100644 index a880df4..0000000 --- a/lib/layout/list/samples/ListContactsSample.css +++ /dev/null @@ -1,57 +0,0 @@ -.list-sample-contacts { - color: white; -} -.list-sample-contacts-list { - background: url(assets/bg.png); -} -/* item */ -.list-sample-contacts-item { - height: 100px; - border-top: 1px solid silver; - padding: 12px 16px; - background-color: #333333; -} -.list-sample-contacts-item-selected { - background: #226B9A url(assets/item-hilite.png) repeat-x bottom; -} -.list-sample-contacts-item > * { - display: inline-block; - vertical-align: middle; -} -.list-sample-contacts-avatar { - width: 32px; - height: 32px; - padding-right: 10px; -} -.list-sample-contacts-description { - font-size: 12px; - color: silver; -} -.list-sample-contacts-remove-button { - float: right; - display: none; -} -/* divider */ -.list-sample-contacts-divider { - background-color: #666; - font-size: 14px; - font-weight: bold; - padding: 8px 14px; -} -/* popup */ -.list-sample-contacts-popup { - width: 280px; -} -.list-sample-contacts-popup > * { - display: block; - margin: 10px 10px; -} -.list-sample-contacts-populate-button { - float: right; - margin-top: 25px; -} -.list-sample-contacts-label { - display: inline-block; - width: 120px; - padding-right: 10px; -} \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.html b/lib/layout/list/samples/ListContactsSample.html deleted file mode 100644 index d288f50..0000000 --- a/lib/layout/list/samples/ListContactsSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Contacts List Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListContactsSample.js b/lib/layout/list/samples/ListContactsSample.js deleted file mode 100644 index e41ce97..0000000 --- a/lib/layout/list/samples/ListContactsSample.js +++ /dev/null @@ -1,261 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListContactsSample", - kind: "FittableRows", - classes: "list-sample-contacts enyo-fit", - components: [ - {kind: "onyx.MoreToolbar", layoutKind: "FittableColumnsLayout", style: "height: 55px;", components: [ - {kind: "onyx.Button", content: "setup", ontap: "showSetupPopup"}, - {kind: "onyx.InputDecorator", components: [ - {name: "newContactInput", kind: "onyx.Input", value: "Frankie Fu"} - ]}, - {kind: "onyx.Button", content: "new contact", ontap: "addItem"}, - {fit: true}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", placeholder: "Search...", style: "width: 140px;", oninput: "searchInputChange"}, - {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px;"} - ]}, - {kind: "onyx.Button", content: "remove selected", ontap: "removeSelected"} - ]}, - {kind: "List", classes: "list-sample-contacts-list enyo-unselectable", fit: true, multiSelect: true, - onSetupItem: "setupItem", components: [ - {name: "divider", classes: "list-sample-contacts-divider"}, - {name: "item", kind: "ContactItem", classes: "list-sample-contacts-item enyo-border-box", onRemove: "removeTap"} - ] - }, - {name: "popup", kind: "onyx.Popup", modal: true, centered: true, classes: "list-sample-contacts-popup", components: [ - {components: [ - {style: "display:inline-block", components:[ - {content: "count:", classes: "list-sample-contacts-label"}, - {name: "countOutput", style: "display:inline-block;", content: "200"} - ]}, - {kind: "onyx.Slider", value: 4, onChanging: "countSliderChanging", onChange: "countSliderChanging"} - ]}, - {components: [ - {content: "rowsPerPage:", classes: "list-sample-contacts-label"}, - {name: "rowsPerPageOutput", style: "display:inline-block;", content: "50"}, - {kind: "onyx.Slider", value: 10, onChanging: "rowsSliderChanging", onChange: "rowsSliderChanging"} - ]}, - {components: [ - {content: "hide divider:", classes: "list-sample-contacts-label"}, - {name: "hideDividerCheckbox", kind: "onyx.Checkbox"} - ]}, - {components: [ - {kind: "onyx.Button", content: "populate list", classes: "list-sample-contacts-populate-button", ontap: "populateList"} - ]} - ]} - ], - rendered: function() { - this.inherited(arguments); - this.populateList(); - }, - setupItem: function(inSender, inEvent) { - var i = inEvent.index; - var data = this.filter ? this.filtered : this.db; - var item = data[i]; - // content - this.$.item.setContact(item); - // selection - this.$.item.setSelected(inSender.isSelected(i)); - // divider - if (!this.hideDivider) { - var d = item.name[0]; - var prev = data[i-1]; - var showd = d != (prev && prev.name[0]); - this.$.divider.setContent(d); - this.$.divider.canGenerate = showd; - this.$.item.applyStyle("border-top", showd ? "none" : null); - } - }, - refreshList: function() { - if (this.filter) { - this.filtered = this.generateFilteredData(this.filter); - this.$.list.setCount(this.filtered.length); - } else { - this.$.list.setCount(this.db.length); - } - this.$.list.refresh(); - }, - addItem: function() { - var item = this.generateItem(enyo.cap(this.$.newContactInput.getValue())); - var i = 0; - for (var di; (di=this.db[i]); i++) { - if (di.name > item.name) { - this.db.splice(i, 0, item); - break; - } - } - // if we hit end of for-loop, add to end of list - if (!di) { - this.db.push(item); - } - this.refreshList(); - this.$.list.scrollToRow(i); - }, - removeItem: function(inIndex) { - this._removeItem(inIndex); - this.$.list.getSelection().remove(inIndex); - this.refreshList(); - }, - _removeItem: function(inIndex) { - var i = this.filter ? this.filtered[inIndex].dbIndex : inIndex; - this.db.splice(i, 1); - }, - removeTap: function(inSender, inEvent) { - this.removeItem(inEvent.index); - return true; - }, - removeSelected: function() { - // get selected items, sort numerically in decending order - var selected = enyo.keys(this.$.list.getSelection().getSelected()); - selected.sort(function(a,b) { return b-a; }); - // remove items one-by-one, starting with last in the list - for (var i=0; i < selected.length; i++) { - this._removeItem(selected[i]); - } - // clear selection, since all selected items are now gone - this.$.list.getSelection().clear(); - // re-render list in current position - this.refreshList(); - }, - populateList: function() { - this.$.popup.hide(); - this.createDb(~~this.$.countOutput.getContent()); - this.$.list.setCount(this.db.length); - this.$.list.setRowsPerPage(~~this.$.rowsPerPageOutput.getContent()); - // - this.hideDivider = this.$.hideDividerCheckbox.getValue(); - //this.$.divider.canGenerate = !this.hideDivider; - // - this.$.list.reset(); - }, - createDb: function(inCount) { - this.db = []; - for (var i=0; i b.name) return 1; - else return 0; - }); - }, - showSetupPopup: function() { - this.$.popup.show(); - }, - searchInputChange: function(inSender) { - enyo.job(this.id + ":search", enyo.bind(this, "filterList", inSender.getValue()), 200); - }, - filterList: function(inFilter) { - if (inFilter != this.filter) { - this.filter = inFilter; - this.filtered = this.generateFilteredData(inFilter); - this.$.list.setCount(this.filtered.length); - this.$.list.reset(); - } - }, - generateFilteredData: function(inFilter) { - var re = new RegExp("^" + inFilter, "i"); - var r = []; - for (var i=0, d; (d=this.db[i]); i++) { - if (d.name.match(re)) { - d.dbIndex = i; - r.push(d); - } - } - return r; - }, - countSliderChanging: function(inSender, inEvent){ - this.$.countOutput.setContent(Math.round(inSender.getValue()) * 50); - }, - rowsSliderChanging: function(inSender, inEvent){ - this.$.rowsPerPageOutput.setContent(Math.round(inSender.getValue()) * 5); - } -}); - -var avatars = [ - "angel.png", - "astrologer.png", - "athlete.png", - "baby.png", - "clown.png", - "devil.png", - "doctor.png", - "dude.png", - "dude2.png", - "dude3.png", - "dude4.png", - "dude5.png", - "dude6.png" -]; -var titles = [ - "Regional Data Producer", - "Internal Markets Administrator", - "Central Solutions Producer", - "Dynamic Program Executive", - "Direct Configuration Executive", - "International Marketing Assistant", - "District Research Consultant", - "Lead Intranet Coordinator", - "Central Accountability Director", - "Product Web Assistant" -]; - -// It's convenient to create a kind for the item we'll render in the contacts list. -enyo.kind({ - name: "ContactItem", - events: { - onRemove: "" - }, - published: { - importance: 0 - }, - components: [ - {name: "avatar", kind: "Image", classes: "list-sample-contacts-avatar"}, - {components: [ - {name: "name"}, - {name: "title", classes: "list-sample-contacts-description"}, - {content: "(415) 711-1234", classes: "list-sample-contacts-description"} - ]}, - {name: "remove", kind: "onyx.IconButton", classes: "list-sample-contacts-remove-button", src: "assets/remove-icon.png", ontap: "removeTap"} - ], - setContact: function(inContact) { - this.$.name.setContent(inContact.name); - this.$.avatar.setSrc(inContact.avatar); - this.$.title.setContent(inContact.title); - }, - setSelected: function(inSelected) { - this.addRemoveClass("list-sample-contacts-item-selected", inSelected); - this.$.remove.applyStyle("display", inSelected ? "inline-block" : "gne"); - }, - renderImportance: function() { - switch(this.importance) { - case 0: - this.$.importance.setContent("not important"); - break; - case -1: - this.$.importance.setContent("important"); - break; - case -2: - this.$.importance.setContent("very important"); - break; - default: - alert(this.importance+" - wowzer"); - break; - } - }, - removeTap: function(inSender, inEvent) { - this.doRemove(inEvent); - return true; - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListLanguagesSample.css b/lib/layout/list/samples/ListLanguagesSample.css deleted file mode 100644 index d938ee6..0000000 --- a/lib/layout/list/samples/ListLanguagesSample.css +++ /dev/null @@ -1,64 +0,0 @@ -.list-sample-language { - color: white; -} -.list-sample-language-list { - background: url(assets/bg.png); -} -.list-sample-language-item { - height: 80px; - border-top: 1px solid #000; - padding: 12px 16px; - background-color: #333333; - position:relative; -} -.list-sample-language-list .rowNumberLabel { - position:absolute; - right:15px; - bottom: 10px; - font-size:12px; -} -.list-sample-language-list .itemLabel { - font-size:24px; - line-height:80px; - padding-left:30px; -} -.list-sample-language-list .serialLabel { - position:absolute; - right:80px; - bottom: 10px; - font-size:12px; -} -.list-sample-language-list .reorderDragger { - background:rgb(0,0,0); -} -.list-sample-language-list .swipeGreen { - background-color:rgb(0,160,40); -} -.list-sample-language-list h2 { - margin:0; - padding:0 0 0 20px; - font-size:24px; - line-height:100px; -} -.list-sample-language-list .dropButton { - width:90px; - height:60px; - position:absolute; - top:20px; - right:110px; -} -.list-sample-language-list .cancelButton { - width:90px; - height:60px; - position:absolute; - top:20px; - right:10px; -} -.list-sample-language-list .swipeTitle { - font-size:30px; - font-weight:bold; - text-align:center; - line-height:100px; - padding:0; - margin:0; -} diff --git a/lib/layout/list/samples/ListLanguagesSample.html b/lib/layout/list/samples/ListLanguagesSample.html deleted file mode 100644 index 74accc7..0000000 --- a/lib/layout/list/samples/ListLanguagesSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Contacts List Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListLanguagesSample.js b/lib/layout/list/samples/ListLanguagesSample.js deleted file mode 100644 index 18ef39f..0000000 --- a/lib/layout/list/samples/ListLanguagesSample.js +++ /dev/null @@ -1,160 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListLanguagesSample", - kind: "FittableRows", - classes: "list-sample-language enyo-fit", - data: [], - languages: { - English: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], - Italian: ["Uno", "Due", "Tre", "Quattro", "Cinque", "Sei", "Sette", "Otto", "Nove", "Dieci"], - Spanish: ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"], - German: ["Eins", "Zwei", "Drei", "Vier", "F\xFCnf", "Sechs", "Sieben", "Acht", "Neun", "Zehn"], - French: ["Un", "Deux", "Trois", "Quatre", "Cinq", "Six", "Sept", "Huit", "Neuf", "Dix"] - }, - components: [ - {kind: "onyx.MoreToolbar", layoutKind: "FittableColumnsLayout", style: "height: 55px;", components: [ - {content: "Rows:"}, - {kind: "onyx.InputDecorator", components: [ - {kind: "onyx.Input", value: "10", name: "numRows" } - ]}, - {kind: "onyx.Button", content: "Repopulate", ontap: "populateList"} - ]}, - {kind: "List", classes: "list-sample-language-list enyo-unselectable", - fit: true, multiSelect: true, - reorderable: true, centerReorderContainer: false, - enableSwipe: true, - onSetupItem: "setupItem", - onReorder: "listReorder", - onSetupReorderComponents: "setupReorderComponents", - // onSetupPinnedReorderComponents: "setupPinnedReorderComponents", - onSetupSwipeItem: "setupSwipeItem", - onSwipeComplete: "swipeComplete", - components: [ - {name: "item", classes: "list-sample-language-item", components: [ - {name: "text", classes: "itemLabel"}, - {name: "rowNumber", classes: "rowNumberLabel"}, - {name: "serial", classes: "serialLabel"} - ]} - ], - reorderComponents: [ - {name: "reorderContent", classes: "enyo-fit reorderDragger", components: [ - {name: "reorderTitle", tag: "h2", allowHtml: true} - ]} - ], - // For Enyo 2.2, we comment out these components to disable pinned mode which is still - // considered a work in progress. - /* pinnedReorderComponents: [ - {name: "pinnedReorderItem", classes: "enyo-fit swipeGreen", components: [ - {name: "pinnedReorderTitle", tag: "h2", allowHtml: true}, - {name: "dropButton", kind: "onyx.Button", ontap: "dropPinnedRow", content: "Drop", classes: "dropButton"}, - {name: "cancelButton", kind: "onyx.Button", ontap: "cancelPinnedMode", content: "Cancel", classes: "cancelButton"} - ]} - ], */ - swipeableComponents: [ - {name: "swipeItem", classes: "enyo-fit swipeGreen", components: [ - {name: "swipeTitle", classes: "swipeTitle"} - ]} - ] - } - ], - rendered: function() { - this.inherited(arguments); - this.populateList(); - }, - listReorder: function(inSender, inEvent) { - var movedItem = enyo.clone(this.data[inEvent.reorderFrom]); - this.data.splice(inEvent.reorderFrom,1); - this.data.splice((inEvent.reorderTo),0,movedItem); - }, - setupItem: function(inSender, inEvent) { - var i = inEvent.index; - if(!this.data[i]) { - return; - } - var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; - var val = this.data[i].val; - var number = this.languages[currentLanguage][val]; - var serial = this.data[i].serial; - this.$.rowNumber.setContent("ROW " + i); - this.$.text.setContent(number); - this.$.serial.setContent("#" + serial); - }, - setupReorderComponents: function(inSender, inEvent) { - var i = inEvent.index; - if(!this.data[i]) { - return; - } - var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; - var val = this.data[i].val; - var number = this.languages[currentLanguage][val]; - this.$.reorderTitle.setContent(number); - }, - /* setupPinnedReorderComponents: function(inSender, inEvent) { - var i = inEvent.index; - if(!this.data[i]) { - return; - } - var currentLanguage = this.data[i].langs[this.data[i].currentIndex]; - var val = this.data[i].val; - var number = this.languages[currentLanguage][val]; - this.$.pinnedReorderTitle.setContent(number); - }, */ - //* Called when the "Drop" button is pressed on the pinned placeholder row - /* dropPinnedRow: function(inSender, inEvent) { - this.$.list.dropPinnedRow(inEvent); - }, */ - //* Called when the "Cancel" button is pressed on the pinned placeholder row - /* cancelPinnedMode: function(inSender, inEvent) { - this.$.list.cancelPinnedMode(inEvent); - }, */ - setupSwipeItem: function(inSender, inEvent) { - var i = inEvent.index; - if(!this.data[i]) { - return; - } - var newLang = (inEvent.xDirection == 1) - ? this.getNextLang(i) - : this.getPrevLang(i); - this.$.swipeTitle.setContent(this.data[i].langs[newLang]); - }, - swipeComplete: function(inSender, inEvent) { - var i = inEvent.index; - this.data[i].currentIndex = (inEvent.xDirection == 1) - ? this.getNextLang(i) - : this.getPrevLang(i); - this.$.list.renderRow(i); - }, - getNextLang: function(index) { - var currentLang = this.data[index].currentIndex; - return (currentLang + 1) % this.data[index].langs.length; - }, - getPrevLang: function(index) { - var currentLang = this.data[index].currentIndex; - return (currentLang - 1 + this.data[index].langs.length) % this.data[index].langs.length; - }, - populateList: function() { - this.createRandomData(); - this.$.list.setCount(this.data.length); - this.$.list.reset(); - }, - createRandomData: function() { - var languages = this.getLanguages(); - var langs; - var dataCount = parseInt(this.$.numRows.getValue(), 10); - this.data = []; - var sortFunc = function() {return 0.5 - Math.random();}; - for(var i=0;i - - - - Basic List Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListNoSelectSample.js b/lib/layout/list/samples/ListNoSelectSample.js deleted file mode 100644 index 0accadb..0000000 --- a/lib/layout/list/samples/ListNoSelectSample.js +++ /dev/null @@ -1,26 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListNoSelectSample", - classes: "list-sample enyo-fit", - components: [ - {name: "list", kind: "List", count: 20000, noSelect: true, multiSelect: false, classes: "enyo-fit list-sample-list", - onSetupItem: "setupItem", components: [ - {name: "item", classes: "list-sample-item enyo-border-box", components: [ - {name: "index", classes: "list-sample-index"}, - {name: "name"} - ]} - ]} - ], - names: [], - setupItem: function(inSender, inEvent) { - // this is the row we're setting up - var i = inEvent.index; - // make some mock data if we have none for this row - if (!this.names[i]) { - this.names[i] = makeName(5, 10, '', ''); - } - var n = this.names[i]; - var ni = ("00000000" + i).slice(-7); - this.$.name.setContent(n); - this.$.index.setContent(ni); - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListOnyxItemSample.html b/lib/layout/list/samples/ListOnyxItemSample.html deleted file mode 100644 index ee59493..0000000 --- a/lib/layout/list/samples/ListOnyxItemSample.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Onyx.Item List Sample - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListOnyxItemSample.js b/lib/layout/list/samples/ListOnyxItemSample.js deleted file mode 100644 index f56dae7..0000000 --- a/lib/layout/list/samples/ListOnyxItemSample.js +++ /dev/null @@ -1,39 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListOnyxItemSample", - classes: "list-sample enyo-fit", - components: [{ - name: "list", - kind: "List", - count: 20000, - multiSelect: false, - classes: "enyo-fit list-sample-list", - onSetupItem: "setupItem", - components: [{ - name: "item", - kind: "onyx.Item", - tapHighlight: true, - classes: "list-sample-item enyo-border-box", - components: [{ - name: "index", - classes: "list-sample-index" - }, { - name: "name" - }] - }] - }], - names: [], - setupItem: function (inSender, inEvent) { - // this is the row we're setting up - var i = inEvent.index; - // make some mock data if we have none for this row - if (!this.names[i]) { - this.names[i] = makeName(5, 10, '', ''); - } - var n = this.names[i]; - var ni = ("00000000" + i).slice(-7); - // apply selection style if inSender (the list) indicates that this row is selected. - this.$.item.addRemoveClass("list-sample-selected", (i % 2 === 0)); - this.$.name.setContent(n); - this.$.index.setContent(ni); - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.css b/lib/layout/list/samples/ListPulldownSample.css deleted file mode 100644 index 1bdf4cf..0000000 --- a/lib/layout/list/samples/ListPulldownSample.css +++ /dev/null @@ -1,15 +0,0 @@ -a:link, a:visited { - color: lightblue; - text-decoration: underline; -} -.list-sample-pulldown-list { - background: grey; -} -.list-sample-pulldown-item { - border-bottom: 1px solid #0E0E0E; - padding: 12px 16px; - background-color: #333333; - /**/ - font-size: 14px; - color: white; -} \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.html b/lib/layout/list/samples/ListPulldownSample.html deleted file mode 100644 index 9574964..0000000 --- a/lib/layout/list/samples/ListPulldownSample.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Pulldown List Sample - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/ListPulldownSample.js b/lib/layout/list/samples/ListPulldownSample.js deleted file mode 100644 index 5e2fd26..0000000 --- a/lib/layout/list/samples/ListPulldownSample.js +++ /dev/null @@ -1,97 +0,0 @@ -enyo.kind({ - name: "enyo.sample.ListPulldownSample", - classes: "enyo-unselectable enyo-fit onyx", - kind: "FittableRows", - components: [ - {kind: "onyx.Toolbar", components: [ - {kind: "onyx.InputDecorator", components: [ - {name: "searchInput", kind: "onyx.Input", value: "enyojs", placeholder: "Enter seach term"}, - {kind: "Image", src: "assets/search-input-search.png", style: "width: 20px;"} - ]}, - {kind: "onyx.Button", content: "search", ontap: "search"} - ]}, - {name: "list", kind: "PulldownList", classes: "list-sample-pulldown-list", fit: true, onSetupItem: "setupItem", onPullRelease: "pullRelease", onPullComplete: "pullComplete", components: [ - {style: "padding: 10px;", classes: "list-sample-pulldown-item enyo-border-box", components: [ - {name: "icon", kind: "Image", style: "float: left; width: 48px; height: 48px; padding: 0 10px 10px 0;"}, - {name: "name", tag: "span", style: "font-weight: bold;"}, - {name: "handle", tag: "span", style: "color: lightgrey;"}, - {name: "date", tag: "span", style: "float: right; color: lightgrey;"}, - {tag: "br"}, - {name: "text", tag: "p", style: "word-wrap: break-word;", allowHtml: true} - ]} - ]} - ], - rendered: function() { - this.inherited(arguments); - this.search(); - }, - pullRelease: function() { - this.pulled = true; - // add 1 second delay so we can see the loading message - setTimeout(enyo.bind(this, function() { - this.search(); - }), 1000); - }, - pullComplete: function() { - this.pulled = false; - this.$.list.reset(); - }, - search: function() { - // Capture searchText and strip any whitespace - var searchText = this.$.searchInput.getValue().replace(/^\s+|\s+$/g, ''); - - if (searchText !== "") { - var req = new enyo.JsonpRequest({ - url: "http://search.twitter.com/search.json", - callbackName: "callback" - }); - req.response(enyo.bind(this, "processSearchResults")); - req.go({q: searchText, rpp: 20}); - } else { - // For whitespace searches, set new content value in order to display placeholder - this.$.searchInput.setValue(searchText); - } - }, - processSearchResults: function(inRequest, inResponse) { - this.results = inResponse.results; - this.$.list.setCount(this.results.length); - if (this.pulled) { - this.$.list.completePull(); - } else { - this.$.list.reset(); - } - }, - setupItem: function(inSender, inEvent) { - var i = inEvent.index; - var item = this.results[i]; - this.$.icon.setSrc(item.profile_image_url); - this.$.name.setContent(item.from_user_name); - this.$.handle.setContent(" @" + item.from_user); - this.$.date.setContent(this.getRelativeDateString(item.created_at)); - this.$.text.setContent(this.parseTweet(item.text)); - }, - getRelativeDateString: function(inDateString) { - var d = new Date(inDateString); - var td = new Date(); - var s; - if (td.toLocaleDateString() == d.toLocaleDateString()) { - var dh = td.getHours() - d.getHours(); - var dm = td.getMinutes() - d.getMinutes(); - s = dh ? dh + " hour" : (dm ? dm + " minute" : td.getSeconds() - d.getSeconds() + " second"); - } else { - var dmo = td.getMonth() - d.getMonth(); - s = dmo ? dmo + " month" : td.getDate() - d.getDate() + " day"; - } - return s.split(" ")[0] > 1 ? s + "s" : s; - }, - parseTweet: function(inText) { - var t = inText; - t = t.replace(/[A-Za-z]+:\/\/[A-Za-z0-9_-]+\.[A-Za-z0-9_:%&~\?\/.=-]+/g, function(url) { - return "" + url + ""; - }); - return t.replace(/[@]+[A-Za-z0-9_-]+/, function(u) { - var username = u.replace("@", ""); - return "@" + username + ""; - }); - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/NameGenerator.js b/lib/layout/list/samples/NameGenerator.js deleted file mode 100644 index 647d102..0000000 --- a/lib/layout/list/samples/NameGenerator.js +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed under Creative Commons Attribution 3.0 License -// attributed to: http://leapon.net/en/random-name-generator-javascript -function rnd(minv, maxv) { - if (maxv < minv) return 0; - return Math.floor(Math.random()*(maxv-minv+1)) + minv; -} - -function makeName(minlength, maxlength, prefix, suffix) { - prefix = prefix || ''; - suffix = suffix || ''; - // these weird character sets are intended to cope with the nature of English (e.g. char 'x' pops up less frequently than char 's') - // note: 'h' appears as consonants and vocals - var vocals = 'aeiouyh' + 'aeiou' + 'aeiou'; - var cons = 'bcdfghjklmnpqrstvwxz' + 'bcdfgjklmnprstvw' + 'bcdfgjklmnprst'; - var allchars = vocals + cons; - var length = rnd(minlength, maxlength) - prefix.length - suffix.length; - if (length < 1) length = 1; - var consnum = 0; - var i; - if (prefix.length > 0) { - for (i = 0; i < prefix.length; i++) { - if (consnum == 2) consnum = 0; - if (cons.indexOf(prefix[i]) != -1) { - consnum++; - } - } - } - else { - consnum = 1; - } - var name = prefix; - for (i = 0; i < length; i++) - { - //if we have used 2 consonants, the next char must be vocal. - if (consnum == 2) - { - touse = vocals; - consnum = 0; - } - else touse = allchars; - //pick a random character from the set we are goin to use. - c = touse.charAt(rnd(0, touse.length - 1)); - name = name + c; - if (cons.indexOf(c) != -1) consnum++; - } - name = name.charAt(0).toUpperCase() + name.substring(1, name.length) + suffix; - return name; -} \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.css b/lib/layout/list/samples/PersistentSwipeableItemSample.css deleted file mode 100644 index 7d5990b..0000000 --- a/lib/layout/list/samples/PersistentSwipeableItemSample.css +++ /dev/null @@ -1,42 +0,0 @@ -.list-sample-persistent-swipeable-item { - color: white; -} -.list-sample-persistent-swipeable-item-list { - background: url(assets/bg.png); -} -.list-sample-persistent-swipeable-item-item { - height: 80px; - border-top: 1px solid #000; - padding: 12px 16px; - background-color:rgba(0,0,0,0.5); -} -.list-sample-contacts-item > * { - display: inline-block; - vertical-align: middle; -} -.list-sample-persistent-swipeable-item-list .itemLabel { - float:left; - font-size:24px; - line-height:80px; - padding-left:20px; -} -.list-sample-persistent-swipeable-item-list .swipeGreen { - background-color:rgba(0,160,40,0.8); -} -.list-sample-persistent-swipeable-item-list .swipeRed { - background-color:rgba(160,0,40,0.8); -} -.list-sample-persistent-swipeable-item-list h2 { - margin:0px; - padding:0px 0px 0px 20px; - font-size:24px; - line-height:100px; -} -.list-sample-persistent-swipeable-item-list .swipeTitle { - font-size:30px; - font-weight:bold; - text-align:center; - line-height:100px; - padding:0px; - margin:0px; -} \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.html b/lib/layout/list/samples/PersistentSwipeableItemSample.html deleted file mode 100644 index c981ab6..0000000 --- a/lib/layout/list/samples/PersistentSwipeableItemSample.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Persistent Swipeable Item Sample - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/layout/list/samples/PersistentSwipeableItemSample.js b/lib/layout/list/samples/PersistentSwipeableItemSample.js deleted file mode 100644 index d10c85b..0000000 --- a/lib/layout/list/samples/PersistentSwipeableItemSample.js +++ /dev/null @@ -1,60 +0,0 @@ -enyo.kind({ - name: "enyo.sample.PersistentSwipeableItemSample", - kind: "FittableRows", - classes: "list-sample-persistent-swipeable-item enyo-fit", - data: ["Cat","Dog","Hippopotamus"], - components: [ - {kind: "List", classes: "list-sample-persistent-swipeable-item-list enyo-unselectable", - fit: true, multiSelect: true, reorderable: false, enableSwipe: true, centerReorderContainer: false, - onSetupItem: "setupItem", - onSetupSwipeItem: "setupSwipeItem", - onSwipeComplete: "swipeComplete", - components: [ - {name: "item", classes: "list-sample-persistent-swipeable-item-item", components: [ - {name: "text", classes: "itemLabel", allowHtml: true} - ]} - ], - swipeableComponents: [ - {name: "swipeItem", classes: "enyo-fit swipeGreen", components: [ - {name: "swipeTitle", classes: "swipeTitle", content: "This is a test"} - ]} - ] - } - ], - rendered: function() { - this.inherited(arguments); - this.populateList(); - }, - populateList: function() { - this.$.list.setCount(this.data.length); - this.$.list.reset(); - }, - setupItem: function(inSender, inEvent) { - if(!this.data[inEvent.index]) { - return; - } - - this.$.text.setContent(this.data[inEvent.index]); - }, - setupSwipeItem: function(inSender, inEvent) { - if(!this.data[inEvent.index]) { - return; - } - - if(inEvent.xDirection === -1) { - // Persist swipeable item if swiped from right to left - this.$.list.setPersistSwipeableItem(true); - this.$.swipeTitle.setContent("This is a persistent item"); - this.$.swipeItem.removeClass("swipeGreen"); - this.$.swipeItem.addClass("swipeRed"); - } else { - // Don't persist swipeable item if swiped from left to right - this.$.list.setPersistSwipeableItem(false); - this.$.swipeTitle.setContent("This is not a persistent item"); - this.$.swipeItem.removeClass("swipeRed"); - this.$.swipeItem.addClass("swipeGreen"); - } - }, - swipeComplete: function(inSender, inEvent) { - } -}); \ No newline at end of file diff --git a/lib/layout/list/samples/assets/avatars/angel.png b/lib/layout/list/samples/assets/avatars/angel.png deleted file mode 100644 index d67d1b76e5d7eeb05d68942f5078a19e3ab35269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2476 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 U7eILG4FCWD07*qoM6N<$f@m=ZtN;K2 diff --git a/lib/layout/list/samples/assets/avatars/athlete.png b/lib/layout/list/samples/assets/avatars/athlete.png deleted file mode 100644 index 8579266ac48d958f1aa035db2351959081f3203f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2070 zcmV+x2 zkl+veK#U*2pMnrVLV^m7ipzkFn|ez}*M+4E$=YU3(p>Gvc8+78`;GTFUe(bX&GJQ$ zY@f^bJ@4~g!{9FKb06Qm6Fm3j0KCJJ$nSI=kF9Q~#k!)MG%e@o-~Tm#;%yy_LMRi8gSQTYB=32?W%I66AY zCtCSG?HS4*d2qCs>u8H3B#Gby0Wb^$$8j6aWjkU_GTHLz{r9!ak54XN*fs)t`laXZ z@6UX3WFX5#A|b?M5yYZl1UQyd@L=06y1QD@n`=i$I?PVZ6dxW*3qPKim+gBcz~0I& zuH}4nM|YB8Sq_50BODfyNJJo!3PFKGe{VY?;UHwWj#^DeGA^c+VEDjR6bRfT|Dk-W zH5kmua*YDSBe`v8dv~V*)ByO%P@Yr5nKzd=g@bjLCkY3v}N+x zHyp-0^Ya*=UU3}HJhv?h{QAV@lJ3~1N9pF-20^9sNnN`Rm%dwO9X;(KYJ9O4Nt(%(B55D!}!F*rO&vvz>dN=-jhN;CFRIaVTP*vE5iA+~J z!l3{-&O?przz*3&b+SC1rP6f)-ih}`;KlDednA)dAOGy*eL45JpEF$t_n`mqM-Y)h zh{ogS&gYRzr^q!5EOHGmQHibx;hmjjxNjWVKe{XX`?2w>*S6$>@4oO%XDllI~xu-t~fg-*ol|oy42h9ZJYLRZD|ADUP+U1K-UOJD&(}$szsuXA(bZR^rxxlh0BWM^2N=XDGvBrQ>8=HZc zizDCNiBBCG=p%Bco_+E|yY88Q2V-|CZlHAhBw{@&q#hii-Y-B^YUFQ@qMzSPK^jI} z&jw2Y$ev$Bd2tP?149V#0)~eN@x;eQx}#CyA;j`jM0%CjRjCryh#l zjllIvD6&eQ=PKZf6$o4um*y%6Q9tml2OA(YcpA%sjp>NAhy3kdp)x%WW+aLHhljxG z6bYfO#{7`Zwqj(k+&Ok${RC}&tify(wsdEM3ysYR-DXWl?xp$zVU9L&0b z!1Mx)*(JDipTdC#5_&sNH9;+7Woa3qSb|Cs+bG$3y@Y7UAK~3z+B!p^r{PabN)!I_ z`-gpCbSJpxNA5ZU$PSd7XISEy7GQ^6$9*3k%+FUOXthCIA2c07*qoM6N<$g7QYz A+W-In diff --git a/lib/layout/list/samples/assets/avatars/baby.png b/lib/layout/list/samples/assets/avatars/baby.png deleted file mode 100644 index 018e8152fca4b3ec39843a65825a39c129ff0fad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1756 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 V2=&|Whywrs002ovPDHLkV1nzTI_v-d diff --git a/lib/layout/list/samples/assets/avatars/devil.png b/lib/layout/list/samples/assets/avatars/devil.png deleted file mode 100644 index 0b2bfff7a3ca1762e71a3dc3bd8d1f56a82aaccb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2236 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 KMNUMnLSTaSV-W}d diff --git a/lib/layout/list/samples/assets/avatars/dude.png b/lib/layout/list/samples/assets/avatars/dude.png deleted file mode 100644 index caf0b64070826e184ce79ed57b1183ee2d44f7fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2196 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 diff --git a/lib/layout/list/samples/assets/avatars/dude5.png b/lib/layout/list/samples/assets/avatars/dude5.png deleted file mode 100644 index c299afdf6125a9383cac6625019ad749deec3492..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2065 zcmV+s2=4cZP)75?VEJG<+B`jOa9Qa5QUx3T56DWXzQDHT#mOeI7@k&uueO2rQlQl(0W z9|ZnZA}DHv6pHv)q>3M)(g2B))`k`lR2OI}Drz@=W!GNsd*?lKXE=AfhO{K9O)~b; z?A*C~&v(xG&SM39!gc)k@ewVV`tJO~{IsI#cb7_e(Xp+@_`Uc1MG%BvF~)v*^5jY9 zlg_!>CEV)ev9EsZSURo06pBhlN+gj@r%941^kpDRB3fMou4yc^O!L@JUU*^d{{bN0 z?8V_DN2Y=3<+kl*{4jzn%TPoCk|@%bBCs$-z1f5t;ci6`&Yw7OV$U4|(Es@3Y2RmO z?I4t*D1s46o zk^oVls1c};yh1kweu%Yto%ST2zLiI}4PbhDTF+)P&j;jUiCdgVAe~O3zmUaXA&*o_ zM?_)ZAu%lrEMn+%I$%OnIC}JGai;*}k1tq^ja1e*R6&qp>t#uS#H}WadF*Y+fnnJ& zJr9=aLXl*6f)CR);Yzgmb^$cknqfDUKqi|bOX)mvy~x4HA~>ip^2zEDhGC#zG1c66l!!et%yBlz6|Am#@wfJq(TH}3##rU`0Vdx?62yi)-G^MzBV zPK||u|8=MFHUiIrBCB951f$#+NL;52QPvQ+HaeyYDK|<*NW@Rip1n5r*UQ0e0XTj7 zbibO=W(6fR{BF%6if|SZx|T$-3F#ifcLR#Qk3D1e;gLof7tWu9ZCS6}b_iC> z<*#^tIP6evTaJs%^DczQMd*9P2Zso0qE@ZppI6?8KK?8Uli$H>=Y9*3JX7p1mG&P# ztnCzlbp6A>DwW3UrJ1o0-hc1Fo_%A&LfOV{aS@i$K)u>PtKI46{=P~TW5i)+vn8O?AP3KQSJM#abXzW+m7ugB0u;>N(h0ES0KsXK1Y2YrQs zVz*iQ!=s;h;)`$1Ub?jH5KK)>J)@^H-xgI};7y2k!7d$G8X7`AqvM0c4ZL{fXRu5o z?vi{q&}ffBT`^lIAel@;Cvk{7S}LuELGY!);h|So78k4A@_@sVoYpf8_`l~a3!=lLWac|wHIYGC}H{g}9a zoWesM(vqK>nE2Glwg3by9PvFjo^}{jIc_;U(1rl3D-{BxB9%!~>!mv2Z31Kgi)X|V zg}^ep7#$hGRr1v8wQ@W&iqyj+Iecnc03`A)pZ|EZW4#u;b$3ajN&o`#Oz5*7Ko(EN zg(#JH3*5jOTLjdho)09L$eA4VkuH|5OuaC%L zK7?|XbER9#X$KNoBA$dg?G~D?77Y4qk#d8$!oyM;>_^1Hhv@hcNuDG_lDwXK{{hf# zcV=spdNSodFTA24#uaW8L=;=U=@AyM@pqK(Xi=twAw#>}CgpZKvN^5;m&iO&>Zfc{ zIR|!=^poUBQrCIozep^r`&@Ztd7M&g-{8>hcH~5>^La>Qk?F?)4J|5VCC`86*lxqN%=vb!K0~46P3dnWYrNciT)}oHd9laf;U1&& vJtlK<*uD4pUW)Oxde7nyNm{+N8(#kgD9-PG+F1#^00000NkvXXu0mjf#HQtt diff --git a/lib/layout/list/samples/assets/avatars/dude6.png b/lib/layout/list/samples/assets/avatars/dude6.png deleted file mode 100644 index 3ed55360e2fa99462f30b433724b835a5773423d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2063 zcmV+q2=MobP)=}C=9y^JXv`uIVG>rt2LO}(TRuw4{_wJBaR|I&SWXUM^^^~)BT0>e(iO7JGhg*{v-|NVQBUQn?-G>?I)Vayg)f#r>oP-8z33-X9R%~}G{oPk47;H+QWe<-UNij0T) zc7u<_aBAdrSP2eC65#j}K3WuD5&7bz3E|C2%XWhe7^u%R+g@(=fV$k>8+6NBpm6M7 zzX#_|55UeXqiahR;4*v;jLy#@C346%haHy@bQ-!`b{=3rf3y9?W)G~J@_O=;hc6nB z;N@3OK-z2}m5M_XCCHStQm>#vMCt|*Hv;Hc8A4wQLQlNZiUds=Xq!ntmL8Sy#>JPR z_azCj1WAxlcTH3&D&tk;M;Jc0s-VrG|Hn8^Z5A;;E%e?M0D8jM*e+%;o35an==OXY zHOI#CVhvqqIUb(xgsLd;z!CU9YBLVDy}tl2@17gG8vqPl4>}7S;E5^J=48}XOe|fR z#FjI0?7FuPeq2Bxa0pzyA*ezenF5M~Zso23=;%ye{r(e2&~R(`b4?5Qy(~d`0zE$ZalUBo8OLY+rAYOQ{yO>dJwEk zqAjjKk|athfCqjA#I=0eLv*}j$ZHa+!9XodHUCxCcJ7&$cufBus+7;wf4-K;cM%puM0q5r-rR4X99mfq?vT%JEmL?yIdH?0*6{bRhN9 z_N4s$6OV6{ySq~;U!TG0t1e2La>!?Fl*b#;5@fw(LJGCuHIUO{_-&ckPh+Lhfa?V4C<0&jhKsJOfK^M! zm61j;HdgOvzIE{UugXhz4B+rVb+e|#E`D$SdhH)H?;A8{drNVM0?|wZs4XQyizQ*# z6SNHT%9UwBI@R`x;b-dDFeosnI?mm7T{Ej4Gmi)7w4;tFls|zR=D!QfoWu=Z zU~BP-LEWwmMI(;A>6Cy%&OoWu0bSRjs48MANuVmwC~-UuUGjY~z|hbN9(5;c{dJD06fQq$9S-oIFw+KqVZn^cS~OiSg)x8 zZDf+y(|xa2p>~_6#8sq{an$P;9LquA*;w%J!|Bf_;l(%5MTPo8N}#9~aoHmIfQn+)V#%i%^S+xggZqb6Aqb*+>9RwHi=zr_Op|cm*)AY~3QkNbdwfZo=%DK*=<-}3uXpqE?vild6SP1zBxEM zdF{~I{>5kMnp|&|9Qc%3u60Jy*Acr+m`?U002ovPDHLkV1n!C*NXrE diff --git a/lib/layout/list/samples/assets/bg.png b/lib/layout/list/samples/assets/bg.png deleted file mode 100644 index 61c031f5cec933d6e13cd6aa3ed851b51015fe6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79561 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 diff --git a/lib/layout/imageview/samples/assets/favicon.ico b/lib/layout/imageview/samples/assets/favicon.ico deleted file mode 100644 index 52c86347fe3e10042c05374362757fa260307d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 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≶vOX3v1YT*-6a0P-=iHnEYXl3EJto&@ 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 z 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 PX8Hcp>S-JVY^?qN=zDMS diff --git a/lib/layout/imageview/samples/assets/jupiter.jpg b/lib/layout/imageview/samples/assets/jupiter.jpg deleted file mode 100644 index 23376edeffdb1eb266041b62b351ebe395c4a40d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27149 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